How to loop through nested JSON and append in HTML DOM - javascript

I am trying to loop through a JSON and append it to HTML in a nested way. What I am trying to do is add a Header tag for the title of the object and have tags for the titles of items. Some objects might not have the items as empty too. I am guessing a nested loop is required and I've tried implementing it. The JSON looks like:
[
{
"id": 1,
"title": "Hello",
"url": "http://localhost:8000/login/notes/1/",
"description": "Hello nice",
"created_at": "2019-08-10T06:02:55.468315Z",
"created_by": "Dude",
"items": [
{
"id": 1,
"url": "http://localhost:8000/login/items/1/",
"title": "baby's toy",
"note": "http://localhost:8000/login/notes/1/"
},
{
"id": 2,
"url": "http://localhost:8000/login/items/2/",
"title": "baby's toy",
"note": "http://localhost:8000/login/notes/1/"
},
{
"id": 4,
"url": "http://localhost:8000/login/items/4/",
"title": "postman5",
"note": "http://localhost:8000/login/notes/1/"
}
]
},
{
"id": 2,
"title": "abc",
"url": "http://localhost:8000/login/notes/2/",
"description": "asad",
"created_at": "2019-08-10T15:23:53.074848Z",
"created_by": "dude2",
"items": [
{
"id": 5,
"url": "http://localhost:8000/login/items/5/",
"title": "Parrot Toy",
"note": "http://localhost:8000/login/notes/2/"
}
]
}]
I've tried
fetch('http://localhost:8000/login/notes/?format=json',{mode: 'cors'})
.then(response => response.json())
.then(data => {
var output='';
var final='';
var semif='';
var darif='';
for (var i in data) {
output+=i+'<h2>'+data[i].title +'</h2>'
for(j in data[i].items){
final+='<li>'+data[i].items[j].title+'</li>'
}
semif=output+final
}
document.getElementById('test').innerHTML=darif
});
HTML
<p id="test">
</p>
What I want to achieve is:
<h1>Hello</h1>
<h5>baby's toy</h5>
<h5>baby's toy</h5>
<h5>postman5</h5>
<h1>abc</h1>
<h5>parrot's toy</h5>

I strongly advise against doing lengthy string concatenations. Strings are immutable objects and they can put unnecessary burden on your system.
In addition, using map and join is much more elegant and easier to read.
const data = [
{
"id": 1,
"title": "Hello",
"url": "http://localhost:8000/login/notes/1/",
"description": "Hello nice",
"created_at": "2019-08-10T06:02:55.468315Z",
"created_by": "Dude",
"items": [
{
"id": 1,
"url": "http://localhost:8000/login/items/1/",
"title": "baby's toy",
"note": "http://localhost:8000/login/notes/1/"
},
{
"id": 2,
"url": "http://localhost:8000/login/items/2/",
"title": "baby's toy",
"note": "http://localhost:8000/login/notes/1/"
},
{
"id": 4,
"url": "http://localhost:8000/login/items/4/",
"title": "postman5",
"note": "http://localhost:8000/login/notes/1/"
}
]
},
{
"id": 2,
"title": "abc",
"url": "http://localhost:8000/login/notes/2/",
"description": "asad",
"created_at": "2019-08-10T15:23:53.074848Z",
"created_by": "dude2",
"items": [
{
"id": 5,
"url": "http://localhost:8000/login/items/5/",
"title": "Parrot Toy",
"note": "http://localhost:8000/login/notes/2/"
}
]
}]
const result = data.map(el => {
return `<h1>${el.title}</h1>` + el.items.map(el => `<h5>${el.title}</h5>`).join("")
}).join("")
console.log(result)

fetch('http://localhost:8000/login/notes/?format=json',{mode: 'cors'})
.then(response => response.json())
.then(data => {
var html = '';
data.forEach(listItem => {
const h1 = `<h1> ${listItem.title} </h1>`;
html+=h1;
listItem.items.forEach(item=> {
const h5 = `<h5> ${item.title} </h5>`;
html+=h5;
});
});
document.getElementById('test').innerHTML=html;
});
I think you may use it.

Related

Big Json parsing in cypress, jsonPath usage

I'm new to cypress and I face a problem when trying to work with json responses. I am getting json with units structure(tree structure) and I need to get all the names from it.
I tried to use jsonpath dependenc and parse json using jp.query, but it doesn't works:
cy.request(*some request*).its('body').then((body) => {
let units = jp.query(body, "$..[?(#.type=='PROJECT')].name");
})
I'm getting obj needs to be an object Assertion error here
How to fix this or maybe there are any other ways to parse json in cypress?
JSON Sample:
[
{
"id": 2,
"name": "Solar",
"children": [
{
"id": 3,
"name": "Earth",
"children": [
{
"id": 4,
"name": "Moon",
"type": "STREAM",
"active": true
}
],
"type": "PROJECT",
"active": true
},
{
"id": 5,
"name": "Jupiter",
"children": [
{
"id": 6,
"name": "Io",
"type": "STREAM",
"active": true
},
{
"id": 7,
"name": "Ganymede",
"type": "STREAM",
"active": true
}
]},
],
"type": "PROGRAM",
"active": true
},
{
"id": 9,
"name": "Centaurus",
"children": [
{
"id": 10,
"name": "Alpha Centauri A",
"children": [
{
"id": 818,
"name": "Alpha Centauri Aa-2345",
"type": "STREAM",
"active": true
}
],
"type": "PROJECT",
"active": true
},
{
"id": 11,
"name": "Alpha Centauri B",
"children": [
{
"id": 12,
"name": "Alpha Centauri Bb",
"type": "STREAM",
"active": true
}
],
"type": "PROJECT",
"active": true
},
],
"type": "PROGRAM",
"active": true
}
]
add below 2 lines before jp.query()
body = JSON.stringify(body);
body = JSON.parse(body);
Depending on how the request/response is configured, you may have one of the following issues
response is a string
body is a string
there is no body
cy.request(*some request*)
.then(response => response.json())
.its('body')
.then(body => {
let units = jp.query(body, "$..[?(#.type=='PROJECT')].name");
})
or
cy.request(*some request*)
.its('body')
.then(body => body.json())
.then(body => {
let units = jp.query(body, "$..[?(#.type=='PROJECT')].name");
})
or
cy.request(*some request*)
.then(response => response.json())
.then(jsonObj => {
let units = jp.query(jsonObj, "$..[?(#.type=='PROJECT')].name");
})

JS Reduce with parent parameter

I am trying to solve my last issue with my reduce function to turn a nested JSON object into a flat list to enable easier searching.
Taking the JSON Below
{
"MovementPatterns": [
{
"Id": "",
"Name": "Warm-up",
"Exercises": [
{
"Id": "",
"Name": "Lizard Stretch",
"Level": 1,
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Pigeon Stretch",
"Level": 1,
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Core Hold",
"Level": 1,
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Superman",
"Level": 1,
"EquipmentRequired": ""
}
]
},
{
"Name": "Horizontal Push",
"Id": "",
"Exercises": [
{
"Id": "",
"Name": "Wall Push-up",
"Level": 0,
"VideoUrl": "",
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Push-up",
"Level": 1,
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Tap Push-up",
"Level": 2,
"EquipmentRequired": ""
},
{
"Id": "",
"Name": "Explosive Push-up",
"Level": 3,
"EquipmentRequired": ""
}
]
}
]
}
I have used the following code:
const exercises = data.MovementPatterns.reduce(
(a, {Exercises}) => [...a, ...Exercises, ...a],
[],
);
To flattern all the exercises from each movement pattern into a pure list of exercises...This is great, but I now need to INCLUDE in that JSON for each exercise the PARENT Movement Pattern ID e.g.
[
{
"Id": "",
"Name": "Lizard Stretch",
"Level": 1,
"MovementPatternId": 1,
"EquipmentRequired": ""
},
....
{
"Id": "",
"Name": "Wall Push-up",
"Level": 1,
"MovementPatternId": 2,
"EquipmentRequired": ""
},
]
Can someone please help me figure out how to do this with my reduce function :)
Thanks
You're almost close. Just append parent's Id as MovementPatternId to the each element of Exercises.
const exercises = ab.MovementPatterns.reduce(
(a, { Exercises, Id }) => [
...a,
...Exercises.map(e => ({ ...e, MovementPatternId: Id }))
],
[]
);

get key:value pair inside sub-blocks

I have the below output from Postman or hitting end point(we can say).
{
"SearchResult": {
"total": 11,
"resources": [
{
"id": "12345",
"name": "GuestType",
"description": "Identity group ",
},
{
"id": "56789",
"name": "Admin",
"description": "",
},
]
}
}
I want to extract "id" and "name" from these values. I see the values are inside sub-blocks.
How to extract these key-value using java-script that need to be put in "Tests" tab in postman?
var obj={
"SearchResult": {
"total": 11,
"resources": [
{
"id": "12345",
"name": "GuestType",
"description": "Identity group ",
},
{
"id": "56789",
"name": "Admin",
"description": "",
},
]
}
}
obj.SearchResult.resources.forEach((o)=>console.log(o.id,o.name));
Below code will return array of objects with id and name only.... Happy coding :)
let data = {
"SearchResult":
{
"total": 11,
"resources": [
{ "id": "12345", "name": "GuestType", "description": "Identity group ", },
{ "id": "56789", "name": "Admin", "description": "", }
]
}
}
let ids = data.SearchResult.resources.map(obj => {
id: obj.id,
name: obj.name
});
Try
let ids = data.SearchResult.resources.map(obj => obj.id);
let names = data.SearchResult.resources.map(obj => obj.name);
let data={ "SearchResult": { "total": 11, "resources": [ { "id": "12345", "name": "GuestType", "description": "Identity group ", }, { "id": "56789", "name": "Admin", "description": "", }, ] } }
let ids = data.SearchResult.resources.map(obj => obj.id);
let names = data.SearchResult.resources.map(obj => obj.name);
console.log(ids);
console.log(names);

How to get the respective JSON object based on id

how to get the respective nested JSON object based on Id. For example below is my complete JSON.
[
{
"id": 1,
"title": "ASD Headquarters",
"items": [
{
"id": 11,
"title": "San Jose",
"items": [
{
"id": 13,
"title": "Jensen Chapman's Team",
"items": [
{
"id": 14,
"title": "Jimmy John"
},
{
"id": 15,
"title": "Daniel Mills"
},
{
"id": 16,
"title": "Chris Boden"
}
]
}
]
},
{
"id": 12,
"title": "Irvine",
"items": [
{
"id": 23,
"title": "Tracey Chapman's Team",
"items": [
{
"id": 24,
"title": "San Jesus"
},
{
"id": 25,
"title": "Fat Albert"
},
{
"id": 26,
"title": "Connor McDavid"
}
]
}
]
},
{
"id": 30,
"title": "San Diego",
"items": [
{
"id": 31,
"title": "Duran Duran's Team",
"items": [
{
"id": 32,
"title": "Amberlynn Pinkerton"
},
{
"id": 33,
"title": "Tony Mejia"
},
{
"id": 34,
"title": "Richard Partridge"
},
{
"id": 35,
"title": "Elliot Stabler"
}
]
},
{
"id": 40,
"title": "Steely Dan's Team",
"items": [
{
"id": 36,
"title": "Tony Stark"
},
{
"id": 37,
"title": "Totally Rad"
},
{
"id": 38,
"title": "Matt Murdock"
},
{
"id": 39,
"title": "Stan Lee"
}
]
}
]
}
]
}
]
From the above json how do i filter only particular nested object which have id as 11 => {"id": 11} using underscore.js
Output which i required is : {
"id":11,
"title":"San Jose",
"items":[
{
"id":13,
"title":"Jensen Chapman's Team",
"items":[
{
"id":14,
"title":"Jimmy John"
},
{
"id":15,
"title":"Daniel Mills"
},
{
"id":16,
"title":"Chris Boden"
}
]
}
]
}
You can use a recursive algorithm to look for an object in the current array as well as the nested ones.
var data = [{"id":1,"title":"ASD Headquarters","items":[{"id":11,"title":"San Jose","items":[{"id":13,"title":"Jensen Chapman's Team","items":[{"id":14,"title":"Jimmy John"},{"id":15,"title":"Daniel Mills"},{"id":16,"title":"Chris Boden"}]}]},{"id":12,"title":"Irvine","items":[{"id":23,"title":"Tracey Chapman's Team","items":[{"id":24,"title":"San Jesus"},{"id":25,"title":"Fat Albert"},{"id":26,"title":"Connor McDavid"}]}]},{"id":30,"title":"San Diego","items":[{"id":31,"title":"Duran Duran's Team","items":[{"id":32,"title":"Amberlynn Pinkerton"},{"id":33,"title":"Tony Mejia"},{"id":34,"title":"Richard Partridge"},{"id":35,"title":"Elliot Stabler"}]},{"id":40,"title":"Steely Dan's Team","items":[{"id":36,"title":"Tony Stark"},{"id":37,"title":"Totally Rad"},{"id":38,"title":"Matt Murdock"},{"id":39,"title":"Stan Lee"}]}]}]}];
console.log(find(12, data));
function find(id, [head, ...tail]) {
if (!head)
return null;
return checkObj(id, head) || find(id, tail);
}
function checkObj(id, obj) {
return obj.id === id ? obj : find(id, obj.items || [])
}
This also uses parameter destructuring in order to conveniently separate the "head" of the array from its "tail".
It could also be done within a single function.
var data = [{"id":1,"title":"ASD Headquarters","items":[{"id":11,"title":"San Jose","items":[{"id":13,"title":"Jensen Chapman's Team","items":[{"id":14,"title":"Jimmy John"},{"id":15,"title":"Daniel Mills"},{"id":16,"title":"Chris Boden"}]}]},{"id":12,"title":"Irvine","items":[{"id":23,"title":"Tracey Chapman's Team","items":[{"id":24,"title":"San Jesus"},{"id":25,"title":"Fat Albert"},{"id":26,"title":"Connor McDavid"}]}]},{"id":30,"title":"San Diego","items":[{"id":31,"title":"Duran Duran's Team","items":[{"id":32,"title":"Amberlynn Pinkerton"},{"id":33,"title":"Tony Mejia"},{"id":34,"title":"Richard Partridge"},{"id":35,"title":"Elliot Stabler"}]},{"id":40,"title":"Steely Dan's Team","items":[{"id":36,"title":"Tony Stark"},{"id":37,"title":"Totally Rad"},{"id":38,"title":"Matt Murdock"},{"id":39,"title":"Stan Lee"}]}]}]}];
console.log(find(12, data));
function find(id, [head, ...tail]) {
if (!head)
return null;
if (head.id === id)
return head;
return find(id, head.items || []) || find(id, tail);
}

Lodash filter nested object

I have the following object containing an array posts:
var posts = {
"posts": [{
"id": 83,
"title": "Onfido helps iCracked win customers’ confidence",
"slug": "onfido-helps-icracked-win-customers-confidence",
"tags": [{
"id": 25,
"slug": "case-studies"
}, {
"id": 10,
"slug": "industry-news"
}]
}, {
"id": 82,
"title": "Machine learning makes banking more personal",
"slug": "machine-learning-makes-banking-more-personal",
"tags": [{
"id": 10,
"slug": "industry-news"
}]
}, {
"id": 81,
"title": "11 reasons to join Onfido",
"slug": "ten-reasons-to-join-onfido",
"tags": [{
"id": 100,
"slug": "our-expertise"
}]
}]
}
Using Lodash, I’d like to extract all posts with tags.slug of value "case-studies". Currently I’ve been trying the following with no luck:
_.filter(posts, function(post) {
_.filter(post.tags, function(tag) {
return _.where(tag, {'slug': 'case-studies'})
})
})
How would I do this?
Lodash
var out = _.filter(posts.posts, function (post) {
return _.some(post.tags, { 'slug': 'case-studies' });
});
Vanilla JS
var out = posts.posts.filter(function (el) {
return el.tags.some(function (tag) {
return tag.slug === 'case-studies';
});
});

Categories

Resources