I am looking for JSON parsing reference, from where I can jump to question and check for Child question based on Yes section. I didn't find anything related to check for child node check in JSON. Angular is my base framework.
some use cases :
on load show Root question,
On selection show next questions which is child of root then go one
jump to number of questions from tree.
treeObj={
"Root_Element": {
"id": "myTree",
"dt": {
"choice": {
"id": '0',
"title": "Which color",
"description": "Choose color ?",
"choice": [
{
"id": 1,
"title": "Yellow",
"description": "Yellow ? ,
"choice": [
{
"id": 5,
"title": "Dark Yellow",
"description": "Dark Yellow ?
},
{
"id": 4,
"title": "Light Yellow",
"description": "Light Yellow ?
}
]
},
{
"id": 2,
"title": "Red",
"description": "Red ?"
},
{
"id": 3,
"title": "Green",
"description": "Green ?
}
]
}
}
}
}
If the number of levels in the JSON object is fixed and if it does not grow dynamically, you can use the ES6 destructuring to read the data from the nested JSON. Below is an example
var metadata = {
title: "Scratchpad",
translations: [
{
locale: "de",
localization_tags: [ ],
last_edit: "2014-04-14T08:43:37",
url: "/de/docs/Tools/Scratchpad",
title: "JavaScript-Umgebung"
}
],
url: "/en-US/docs/Tools/Scratchpad"
};
var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;
console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"
Related
I am trying to return a filtered JSON response using jQuery after a successful GET request of the original JSON response. The original JSON response is an array of our products within our Shopify store for the given collection page the user is on. I am trying to filter the full JSON response down to a new JSON response that filters out all products that don't contain the tag the user has selected from a dropdown. The tag the user selected is the input of the getFilterProducts function.
Here is an example of the JSON:
{
products: [
{
"id": 1,
"title": "white shirt",
"tags": [
"small"
"medium"
"large"
]
},
{
"id": 2,
"title": "black shirt",
"tags": [
"medium"
"large"
]
},
{
"id": 3,
"title": "blue shirt",
"tags": [
"small"
"medium"
"large"
]
}
]
}
Here is the code for the jQuery GET:
function getFilterProducts(tag){
$.ajax({
type: 'GET',
url: coll_url + '/products.json',
dataType: 'json',
success: function(res){
var productArray = $(res.products).filter(function() {
return res.products.tags === tag;
});
console.log(productArray);
},
error: function(status){
alert(status);
}
})
}
So if a users selected the tag "Small" from the dropdown, it should find which products have the tag "Small" and return a new JSON response with just the White and Blue shirt in it.
I feel like I am close but just can't wrap my head around why the response keeps coming back empty for every tag.
Use jQuery.inArray()
var productArray = res.products.filter(function(product) {
return jQuery.inArray(tag, product.tags) !== -1;
});
var res = {
products: [{
"id": 1,
"title": "white shirt",
"tags": [
"small",
"medium",
"large"
]
},
{
"id": 2,
"title": "black shirt",
"tags": [
"medium",
"large"
]
},
{
"id": 3,
"title": "blue shirt",
"tags": [
"small",
"medium",
"large"
]
}
]
};
tag = 'small';
var productArray = res.products.filter(function(product) {
return jQuery.inArray(tag, product.tags) !== -1;
});
console.log( productArray );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You could use JS's (not jQuery's) Array.prototype.filter() and Array.prototype.includes()
const res = {
products: [{
"id": 1,
"title": "white shirt",
"tags": [
"small",
"medium",
"large",
]
},
{
"id": 2,
"title": "black shirt",
"tags": [
"medium",
"large",
]
},
{
"id": 3,
"title": "blue shirt",
"tags": [
"small",
"medium",
"large",
]
}
]
};
const tag = "small";
const productArray = res.products.filter(item => item.tags.includes(tag));
console.log(productArray);
Here's a small reminder of what jQuer .filter() does and how it works: https://api.jquery.com/filter/
WARNING: Your json is malformed. The following has been correct:
{
"products": [
{
"id": 1,
"title": "white shirt",
"tags": [
"small",
"medium",
"large"
]
},
{
"id": 2,
"title": "black shirt",
"tags": [
"medium",
"large"
]
},
{
"id": 3,
"title": "blue shirt",
"tags": [
"small",
"medium",
"large"
]
}
]
}
Here is the code you are looking for:
We check for every product that the tag list contains the tag we want.
Call the filterProducts function when the ajax operation succeeded. I cut the ajax part for demonstration purposes.
const JSON_DATA = JSON.parse(`{"products":[{"id":1,"title":"white shirt","tags":["small","medium","large"]},{"id":2,"title":"black shirt","tags":["medium","large"]},{"id":3,"title":"blue shirt","tags":["small","medium","large"]}]}`);
const TAG = "small";
function filterProducts(json_products, tag) {
if(json_products === undefined || tag === undefined) return [];
return json_products.products.filter((product) =>
product.tags.includes(tag)
);
}
console.log(filterProducts(JSON_DATA, TAG));
Hope it helps :)
I have this JSON which I'm parsing using NodeJS and it needs to be restructured into the second JSON which I've added below.
In the first JSON, the rows object has two pages objects (any number of pages objects can be present) which contains all the same keys and values with the exception of values and display keys.
{
"pages": [
{
"label": "SomeLabel",
"name": "Some",
"sections": [
{
"type": "Repeat",
"label": "Label 1",
"name": "Name 1",
"rows": [
{
"pages": [
{
"label": "Label 1",
"name": "Name 1",
"sections": [
{
"type": "Flow",
"label": "Label 2",
"name": "Name 2",
"answers": [
{
"label": "Question Label",
"question": "Question",
"values": [
"Value A"
],
"valuesMetadata": [
{
"display": "Display A",
"row": {
"columns": []
}
}
]
}
]
}
]
}
]
},
{
"pages": [
{
"label": "Label 1",
"name": "Name 1",
"sections": [
{
"type": "Flow",
"label": "Label 2",
"name": "Name 2",
"answers": [
{
"label": "Question Label",
"question": "Question",
"values": [
"Value B"
],
"valuesMetadata": [
{
"display": "Display B",
"row": {
"columns": []
}
}
]
}
]
}
]
}
]
}
],
"footer": null
}
]
}
]
}
In the second JSON the rows object has a single pages object, inside of which the values and display keys have multiple values (the non-common values).
{
"pages": [
{
"label": "SomeLabel",
"name": "Some",
"sections": [
{
"type": "Repeat",
"label": "Label 1",
"name": "Name 1",
"rows": [
{
"pages": [
{
"label": "Label 1",
"name": "Name 1",
"sections": [
{
"type": "Flow",
"label": "Label 2",
"name": "Name 2",
"answers": [
{
"label": "Question Label",
"question": "Question",
"values": [
"Value A",
"Value B"
],
"valuesMetadata": [
{
"display": [
"Display A",
"Display B"
],
"row": {
"columns": []
}
}
]
}
]
}
]
}
]
}
],
"footer": null
}
]
}
]
}
So, I want to know the fast and easy steps to do this. Please let me know the process and methods to solve this.
Thanks
If I understand you correctly, you want to combine all pages in a single page that holds all information.
This can be achieved using the Array.reduce function. reduce takes an array and combines all elements to a single value using a function (provided by you) to combine the first two elements until only one is left (i.e. 1 * 2 => new1; new1 * 3 => new2 where * represents your function).
Your problem would look something like this:
rows[0].pages = rows[0].pages.reduce((currentElement, currentState) => {
if (!currentState) { // first iteration return first element but make sure display is an array
currentElement.sections[0].answers[0].valuesMetadata[0].display =
[currentElement.sections[0].answers[0].valuesMetadata[0].display];
return currentElement;
}
// add values of current element to arrays in current state
currentState.sections[0].answers[0].values
.concat(currentElement.sections[0].answers[0].values);
currentState.sections[0].answers[0].valuesMetadata[0].display
.concat(currentElement.sections[0].answers[0].valuesMetadata[0].display);
return currentState;
});
currentElement is the object of the array that is currently reduced, currentState is the intermediate result of the reduction.
PS:
The object looks like you are way too many arrays where you would not need them. The given code snippet works only for the first element in each array (hence the [0]s. If you really do have multiple values in each array you would have to iterate over all of those accordingly.
I'll get from the API a deeply nested state - e.g.:
[{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": []
}]
}]
}]
}]
(Please ignore duplicate ids etc)
Now here are the requirements:
I need to properly render this
e.g.
<div>
text
<div>
text
</div>
</div>
I need to be able to update the nested state within redux store
This list can be huge - like at least 3k items (which theoretically works fine)
What I tried:
Having everything unnested:
Rendering is very complicated (with parentId)
Maintaining the structure is difficult (need to flatten and unflatten it) -> this costs a lot of performance
Having everything nested:
Updating the store is impossible without "cheating" in react -> manipulating the state directly
What can be a solution to this? What should be the architecture
Something like immutability-helper will probably be of use to you here.
const state = [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": []
}]
}]
}]
}];
const newState = update(state, {
0: {
children: {
0: {
children {
0 : {
children: {
0: {
"id": { $set: 2}
}
}
}
}
}
}
};
return newState;
[{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 1,
"text": "test",
"children": [{
"id": 2,
"text": "test",
"children": []
}]
}]
}]
}];
The 0s here could be replaced with some indexes in your payload; I just used 0 here as the example arrays all have only 1 element in them. This is quite deeply nested though so as the comments pointed out, any flattening you can do will make the updates easier.
I want to find single json objec based on ID, from below tree.
example - getObjeById(4),
it should return obj from below tree. need help on this.
data={
"mytree": {
"id": "dectree",
"dt": {
"choice": {
"id": 0,
"title": "Which color",
"description": "Choose color ?",
"choice": [
{
"id": 1,
"title": "Yellow",
"description": "Yellow ? ",
"choice": [
{
"id": 5,
"title": "Dark Yellow",
"description": "Dark Yellow ,
"choice": [
{
"id": 6,
"title": "id 6 yello",
"description": "<span> last leaf for yello </span>"
}]
},
{
"id": 4,
"title": "Light Yellow",
"description": "Light Yellow
}
]
},
{
"id": 2,
"title": "Red",
"description": "Red ?"
},
{
"id": 3,
"title": "Green",
"description": "Green
},
{
"id": 7,
"title": "white",
"description": "white color",
"choice": [
{
"id": 8,
"title": "id 8 white",
"description": "<span> last leaf for white </span>"
}]
}
]
}
}
}
}
Below is a snippet showcasing a recursive search function.
As warned, this function takes approximately 6 milliseconds to search this tree, about a third of a standard 60 fps frame.
var data = {
"mytree": {
"id": "dectree",
"dt": {
"choice": {
"id": 0,
"title": "Which color",
"description": "Choose color ?",
"choice": [{
"id": 1,
"title": "Yellow",
"description": "Yellow ? ",
"choice": [{
"id": 5,
"title": "Dark Yellow",
"description": "Dark Yellow",
"choice": [{
"id": 6,
"title": "id 6 yello",
"description": "<span> last leaf for yello </span>"
}]
}, {
"id": 4,
"title": "Light Yellow",
"description": "Light Yellow"
}]
}, {
"id": 2,
"title": "Red",
"description": "Red ?"
}, {
"id": 3,
"title": "Green",
"description": "Green"
}, {
"id": 7,
"title": "white",
"description": "white color",
"choice": [{
"id": 8,
"title": "id 8 white",
"description": "<span> last leaf for white </span>"
}]
}]
}
}
}
};
//Here comes the recursive function
function searchTree(data, idLabel, idValue, results) {
if (idLabel === void 0) {
idLabel = "id";
}
if (idValue === void 0) {
idValue = "0";
}
if (results === void 0) {
results = [];
}
var keys = Object.keys(data);
keys.forEach(function search(key) {
if (typeof data[key] == "object") {
results = searchTree(data[key], idLabel, idValue, results);
} else {
if (data[key] == idValue && key == idLabel) {
results.push(data);
}
}
});
return results;
}
console.log("Looking for 4:", searchTree(data, "id", "4"));
console.log("Looking for 6:", searchTree(data, "id", "6"));
EDIT - flat structure
An ideal structure would properly look more like this:
var data = [{
id: 1,
title: "Yellow",
description: "Yellow ? ",
choices: [4, 5]
}, {
id: 2,
title: "Red",
description: "Red ?",
choices: []
}, {
id: 3,
title: "Green",
description: "Green",
choices: []
}, {
id: 4,
title: "Light Yellow",
description: "Light Yellow",
choices: []
}, {
id: 5,
title: "Dark Yellow",
description: "Dark Yellow",
choices: [6]
}, {
id: 6,
title: "id 6 yello",
description: "<span> last leaf for yello </span>",
choices: []
}, {
id: 7,
title: "white",
description: "white color",
choices: [8]
}, {
id: 8,
title: "id 8 white",
description: "<span> last leaf for white </span>",
choices: []
}];
console.log("Get elements with id == 7", data.filter(function(i) {
return i.id === 7
})[0]);
console.log("Get elements with id == 2", data.filter(function(i) {
return i.id === 1
})[0]);
console.log("Get elements with id == 3 or id == 4", data.filter(function(i) {
return i.id === 3 || i.id === 4
}));
With a structure like above, traversing the tree using filter becomes trivial. Approximately 2 milliseconds calculation time on this structure and it should scale much better.
From here, we could also easily sort our list or manipulate it in a bunch of ways using optimized, native functionality.
is there any way to find immeida parent form node ? I am geeting specific now example id : 5 and it maye be part of one parent whcih is id:3.
I have two models 'Author' and 'Publisher' (Rails), with a publisher hasOne author / author belongsTo publisher relationship.
I have the Ember models setup correctly -- JS Fiddle -- and the associations working when I manually push into the store. But only the publisher records are created when requesting /publishers index.
I've tried several types of JSON responses:
Publishers with author
{
"publishers": [
{
"id": 1,
"name": "Test P 1",
"author": 1
}
],
"author": {
"id": 1,
"name": "Test A 1",
"publisher": 1
}
}
Publishers with authors
{
"publishers": [
{
"id": 1,
"name": "Test P 1",
"author": 1
}
],
"authors": [{
"id": 1,
"name": "Test A 1",
"publisher": 1
}]
}
Publishers with author embedded
{
"publishers": [
{
"id": 1,
"name": "Test P 1",
"author": {
"id": 1
"name": "Test A 1"
}
}
]
}
Thanks for any help!
The ActiveModelAdapter/ActiveModelSerializer expects _id/_ids to be appended on relationships
{
"publishers": [
{
"id": 1,
"name": "Test P 1",
"author_id": 1
}
],
"authors": [{
"id": 1,
"name": "Test A 1",
"publisher_id": 1
}]
}
http://jsfiddle.net/6Z2AL/1/
Adding a link to ember-data issue in case it helps anyone -- single object push payload