Related
I have JSON file with this structure:
{
"launches": [{
"name": "First Name"
}],
"launches": [{
"name": "Second Name"
}],
"launches": [{
"name": "Third Name"
}],
"launches": [{
"name": "Fourth Name"
}]
}
I add the data like this:
$('#div-name').append(d.name);
When this is displayed on a webpage, it is placed in one div with no spaces. I can add a <p> tag to the append, but that still displays ALL the data and creates new divs to display it.
Basically, what I am trying to do is to create a div for each separate "name" value and display only one value per div.
First of all, your "json" is not a valid json, remmeber that in a json object, you can not have duplicated keys. You can easily use an online validator to help you with that... and after you fix it, let's assume that what you actually have is an array of objects like:
[
{"name": "Falcon 9"},
{"name": "Orion"},
{"name": "PSLV"},
{"name": "Soyuz"}
]
with this valid json, you can easily loop trough all the elements like (and take that you are using jQuery):
var json = [ ... ];
$(function() {
$.each(json, function(i, item){
$("p").append("<div>" + item.name + "</div>");
});
});
here's a live test: https://jsbin.com/bixadegeye/1/edit?html,css,js,output
A slightly different way of going about it:
var data = {
"names": [
"Falcon 9",
"Orion",
"PSLV",
"Soyuz"
]
};
$.each( data["names"], function( key, value ) {
$('#div-name').append(value+"<br />");
});
Consider the following example:
var products = {
"Products": [{
"Title": "A",
"Categories": [{
"Name": "Type",
"Properties": ["Type 1", "Type 2", "Type 3"]
}, {
"Name": "Market",
"Properties": ["Market 1", "Market 2", "Market 3", "Market 4"]
}, {
"Name": "Technology",
"Properties": ["Tech 1", "Tech 2"]
}]
}, {
"Title": "B",
"Categories": [{
"Name": "Type",
"Properties": ["Type 1", "Type 3"]
}, {
"Name": "Market",
"Properties": "Market 1"
}, {
"Name": "Technology",
"Properties": ["Tech 1", "Tech 3"]
}]
}, {
"Title": "C",
"Categories": [{
"Name": "Type",
"Properties": ["Type 1", "Type 2", "Type 3"]
}, {
"Name": "Market",
"Properties": ["Market 2", "Market 3"]
}, {
"Name": "Technology",
"Properties": ["Tech 2", "Tech 3"]
}]
}]
}
I'm trying to filter products by their properties so consider I'm using an array to keep track of my selected filters:
var filters = ['Type 3', 'Tech 1'];
With these filters I would like to return product A and product B.
I currently have this:
var flattenedArray = _.chain(products).map('Categories').flatten().value();
var result= _.some(flattenedArray , ['Properties', 'Tech 1']);
But I'm stuck on how to combine the properties for a combined search.
Use _.filter() to iterate the products. For each product combine the list of properties using _.flatMap(), and use _.intersection() and _.size() to find the amount of filters that exist in the categories. Compare that to the original number of filters, and return comparison's response.
var products = {"Products":[{"Title":"A","Categories":[{"Name":"Type","Properties":["Type 1","Type 2","Type 3"]},{"Name":"Market","Properties":["Market 1","Market 2","Market 3","Market 4"]},{"Name":"Technology","Properties":["Tech 1","Tech 2"]}]},{"Title":"B","Categories":[{"Name":"Type","Properties":["Type 1","Type 3"]},{"Name":"Market","Properties":"Market 1"},{"Name":"Technology","Properties":["Tech 1","Tech 3"]}]},{"Title":"C","Categories":[{"Name":"Type","Properties":["Type 1","Type 2","Type 3"]},{"Name":"Market","Properties":["Market 2","Market 3"]},{"Name":"Technology","Properties":["Tech 2","Tech 3"]}]}]};
var filters = ['Type 3', 'Tech 1'];
var result = _.filter(products.Products, function(product) {
return filters.length === _(product.Categories)
.flatMap('Properties')
.intersection(filters)
.size();
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
If I understand you question correctly, this code may help:
_.filter(
products.Products,
product => _.difference(
filters,
_.chain(product.Categories).map(category => category.Properties).flatten().value()
).length === 0
);
It calculates a union of all properties for each product:
_.chain(product.Categories).map(category => category.Properties).flatten().value()
And then checks that it contains all filters array elements, using _.difference method.
Hope it helps.
another fancy way through _.conforms
var res = _.filter(
products.Products,
_.conforms({'Categories': function(categories) {
return _.chain(categories)
.flatMap('Properties') // flat arrays
.uniq() // remove dublicates
.keyBy() // transform to objects with Properties keys
.at(filters) // get objects values by filters
.compact() // remove undefineds
.size() // get size
.eq(filters.length) // compare to filters size
.value();
}
}))
This will work for a list of items where the givenProperty you want to filter on is either a string like 'doorColour' or an array of strings representing the path to the givenProperty like ['town', 'street', 'doorColour'] for a value nested on an item as town.street.doorColour.
It also can filter on more than one value so you could you just need pass in an array of substrings representing the string values you want to keep and it will retain items that have a string value which contains any substring in the substrings array.
The final parameter 'includes' ensures you retain these values if you set it to false it will exclude these values and retain the ones that do not have any of the values you specified in the substrings array
import { flatMap, path } from 'lodash/fp';
const filteredListForItemsIncludingSubstringsOnAGivenProperty = (items, givenProperty, substrings, including=true) => flatMap((item) =>
substrings.find((substring) => path(givenProperty)(item) && path(givenProperty)(item).includes(substring))
? including
? [item]
: []
: including
? []
: [item])(items);
E.g. fLFIISOAGP(contacts, ['person','name'], ['Joh','Pau',Pet']);
with items of structure {contact, business:null, personal:{name:'John'}}.
For the original question - this will also work - I would use this repeatedly on a list of items to filter with different keys to filter on more than one property.
const firstFilteredResult = filteredListForItemsIncludingSubstringsOnAGivenProperty(
products.Products,
["Categories", "0", "Properties"],
["Type 3"]);
const secondFilteredResult = filteredListForItemsIncludingSubstringsOnAGivenProperty(
firstFilteredResult,
["Categories", "2", "Properties"],
["Tech 1"]);
expect(secondFilteredResult[0]['Title']).to.equal( "A");
expect(secondFilteredResult[1]['Title']).to.equal( "B");
expect(secondFilteredResult.length).to.equal(2);
I need to replace multiple occurrence of property value in a json request using JavaScript. I have tried this in JSFiddle and it worked but the same code in an Apigee JavaScript policy is not replacing the value.
I have json data as follows:
[
{
"Name": "app1",
"groups": [
{
"desc": "this is a test group",
"id": "test1",
"name": "test grp45"
},
{
"desc": "this is another test group",
"id": "test2",
"name": "test group 2"
}
],
"id": "1"
},
{
"Name": "app2",
"groups": [
{
"desc": "this is a test group",
"id": "test3",
"name": "test group 4"
},
{
"desc": "this is another test group",
"id": "test4",
"name": "test group 4"
}
],
"id": "2"
},
{
"Name": "app3",
"groups": [
{
"desc": "this is a test group",
"id": "test5",
"name": "test group 5"
},
{
"desc": "this is another test group",
"id": "test6",
"name": "test group 6"
}
],
"id": "3"
}
]
Here's what I have tried:
var val = context.getVariabl("request.content");
context.setVariable("val", val);
function findAndReplace(val1, value, replacevalue) {
for (var x in val1) {
if (typeof val1[x] == typeof {}) {
findAndReplace(val1[x], value, replacevalue);
}
if (val1[x] == value) {
val1["name"] = replacevalue;
//break; // uncomment to stop after first replacement
}
}
}
findAndReplace(val, "test1", "img");
var result = JSON.stringify(val);
var obj = JSON.parse(result);
context.setVariable("response.content", obj);
I want to replace the value of "test1" to "img".
First, you're setting response.content with the parsed obj. You'd want:
context.setVariable("response.content", result);
...instead, because the flow variable needs to be a string, not a JavaScript object.
Second, you're getting request.content and then setting response.content. You probably only want one or the other, especially considering that likely this policy is attached to the request OR the response flow, not both (you can't set the request in the response flow, and content.response would be overwritten by the target response).
Use the Apigee trace tool to see where in the flow your policy is executing, and to inspect the variables being set -- this will help you figure out what you need to fix.
As suggested above you have a couple of things to do to get this to work.
First I would suggest you use two policies. The javascript sample above would be called in the request flow - the one above would store a stringified version of the object into an intermediate flow variable say "foo" as below:
var val = JSON.parse(context.getVariable("request.content"));
findAndReplace(val, "test1", "img");
context.setVariable("foo",JSON.stringify(val));
In the response flow you can then use an assign message policy to insert "foo" into the response. As below:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="assignFoo">
<DisplayName>assignFoo</DisplayName>
<FaultRules/>
<Properties/>
<Set>
<Headers/>
<Payload contentType="application/json; charset=utf-8">{foo}</Payload>
<StatusCode>200</StatusCode>
<ReasonPhrase>OK</ReasonPhrase>
</Set>
<AssignTo createNew="false" transport="http" type="response" />
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
Use string replace()
This converts the JSON into string
JSON.stringify(json).replace("test1", "img")
and then you could convert it back to JSON with replaced values
JSON.parse(json)
[
{
"id": 1,
"title": "my Item",
"body": ""
},
{
"id": 2,
"title": "my Item 2",
"body": ""
},
{
"id": 3,
"title": "my Item 3",
"body": ""
}
]
Is above json structure good for storing says users viewed books? I have other key like users' setting so I try to nested/group things to be neater. My question is how can I check an object with value exist or not so I won't insert duplicated data. How to check the id 2 is existed in this case? Do I have to loop?
Do I have to loop?
Yes you have to loop ( or use a method which will do it) :
var idToCheck="id";
var valToCheck=2;
var a = your array...
var wasFound=false;
a.forEach(function(entry) {
if (entry[idToCheck]==valToCheck)
{
wasFound=true;
return;
}
});
//do whatever with `wasFound`.
http://jsbin.com/jigefamiqu/1/edit
I am getting a JSON in response from server:
{
"width": "765",
"height": "990",
"srcPath": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_MERGED_/1273.pdf",
"coverPage": "",
"documents": [
{
"index": "1",
"text": "Archiving Microsoft® Office SharePoint® Server 2007 Data with the Hitachi Content Archive Platform and Hitachi Data Discovery for Microsoft SharePoint",
"type": "doc",
"id": "HDS_054227~201106290029",
"children": [
{
"text": "Page 1",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_1.png"
},
{
"text": "Page 2",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_2.png"
}
]
},
{
"index": "11",
"text": "Brocade FCoE Enabling Server I/O Consolidation",
"type": "doc",
"id": "HDS_053732~201105261741",
"children": [
{
"text": "Page 1",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_053732~201105261741/image_1.png"
},
{
"text": "Page 2",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_053732~201105261741/image_2.png"
}
]
}
]
}
And I want to get pagelocation of the children.
Can anyone tell me how to do this?
Hi
i also want to get indexes from this and then want to get pagelocations of that particular children. Can you tell me how would i do that?
And also when i when i am getting indexes array it is returning me ,, only and not the index nos.
I am using following code for that :
indexes=response.documents.map(function(e){ return e.children.index; })
Thanks & Regards
If you're interested in simply retrieving all the page locations, you can do it using filter:
var locations = [];
json.documents.forEach(function(e,i) {
e.children.forEach(function(e2,i2) {
locations.push(e2.pageLocation);
)}
});
// returns flat array like [item1,item2,item3,item4]
You can get an array of arrays using map:
var locations = [];
var locations = json.documents.map(function(e) {
return e.children.map(function(e2) {
return e2.pageLocation;
});
});
// returns 2-dimensional array like [[item1,item2],[item1,item2]]
Your json response is an appropriate javascript object So you can access all elements of the object like you do as in back end.
here, you have an array of object of the type documents and each document object has array of objects of the type children. so
syntax would be
myjson.documents[0].children[0].pagelocation
( = http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_1.png)
will give you the very first page location..
and so on