Mapping nested JSON despite variable key name and colon character - javascript

I'm trying to get to nested layers, like "title", in JSON data. However, first property is variable and the : character within isn't helping either
"ISBN:nnnnnnnnnnnn"
Mapping values to component to be destructured using:
renderBooks()
{
return this.state.books.map((book, index) =>
<BookDetail key={index} book={book} />);
}
render()
{
console.log(this.state);
return (
<ScrollView style={{ flex: 1 }}>
{this.renderBooks()}
</ScrollView>
);
}
Component:
const BookDetail = ({ book }) =>
{
const { title, author,... } = book;
return (
<Card>
<CardSection>
<View style={styles.headerContentStyle}>
<Text style={headerTextStyle}>{title}</Text>
<Text>{author}</Text>
</View>
</CardSection>
</Card>
);
};
JSON:
[
{
"ISBN:9780192853462": {
"publishers": [
{
"name": "Oxford University Press, USA"
}
],
"identifiers": {
"isbn_13": [
"9780192853462"
],
"openlibrary": [
"OL7384519M"
],
"isbn_10": [
"0192853465"
],
"librarything": [
"49548"
],
"goodreads": [
"334271"
]
},
"subtitle": "A Very Short Introduction (Very Short Introductions)",
"title": "Social and Cultural Anthropology",
"url": "https://openlibrary.org/books/OL7384519M/Social_and_Cultural_Anthropology",
"number_of_pages": 168,
"cover": {
"small": "https://covers.openlibrary.org/b/id/119856-S.jpg",
"large": "https://covers.openlibrary.org/b/id/119856-L.jpg",
"medium": "https://covers.openlibrary.org/b/id/119856-M.jpg"
},
"subjects": [
{
"url": "https://openlibrary.org/subjects/ethnology",
"name": "Ethnology"
}
],
"publish_date": "April 7, 2000",
"key": "/books/OL7384519M",
"authors": [
{
"url": "https://openlibrary.org/authors/OL656666A/John_Monaghan",
"name": "John Monaghan"
},
{
"url": "https://openlibrary.org/authors/OL2662612A/Peter_Just",
"name": "Peter Just"
}
],
"ebooks": [
{
"formats": {},
"preview_url": "https://archive.org/details/socialculturalan00mona",
"availability": "restricted"
}
]
}
}

You could make your own copy of the book object, all the book information is wrapped inside the ISBN attribute, personaly I would have made it a simple field inside the book object.
let data = {
"ISBN:9780192853462": {
"publishers": [
{
"name": "Oxford University Press, USA"
}
],
"identifiers": {
"isbn_13": [
"9780192853462"
],
"openlibrary": [
"OL7384519M"
],
"isbn_10": [
"0192853465"
],
"librarything": [
"49548"
],
"goodreads": [
"334271"
]
},
"subtitle": "A Very Short Introduction (Very Short Introductions)",
"title": "Social and Cultural Anthropology",
"url": "https://openlibrary.org/books/OL7384519M/Social_and_Cultural_Anthropology",
"number_of_pages": 168,
"cover": {
"small": "https://covers.openlibrary.org/b/id/119856-S.jpg",
"large": "https://covers.openlibrary.org/b/id/119856-L.jpg",
"medium": "https://covers.openlibrary.org/b/id/119856-M.jpg"
},
"subjects": [
{
"url": "https://openlibrary.org/subjects/ethnology",
"name": "Ethnology"
}
],
"publish_date": "April 7, 2000",
"key": "/books/OL7384519M",
"authors": [
{
"url": "https://openlibrary.org/authors/OL656666A/John_Monaghan",
"name": "John Monaghan"
},
{
"url": "https://openlibrary.org/authors/OL2662612A/Peter_Just",
"name": "Peter Just"
}
],
"ebooks": [
{
"formats": {},
"preview_url": "https://archive.org/details/socialculturalan00mona",
"availability": "restricted"
}
]
}
};
//let isbn = Object.keys(obj).find(item => item.match(/ISBN:\d/));
const destructureBook = (obj) => {
let book = {};
Object.keys(obj).map(function(key) {
if(key.match(/ISBN:\d/)) book['isbn'] = key;
Object.keys(obj[key]).map(field => book[field] = obj[key][field]);
});
return book;
}
// destructure the return of the function
const {isbn, title, publish_date } = destructureBook(data);
console.log(isbn, title, publish_date)

Related

Generate dynamic payload as per nested array item click javascript

I have this JSON data:
{
"data": [
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iug",
"title": "Art"
},
"subcategories": [
{
"documentId": "c8kr7nv012vtr8vm3l8g",
"title": "Architecture"
},
{
"documentId": "c8kr7nv012vtr8vm3lag",
"title": "Dance"
},
{
"documentId": "c8kr7nv012vtr8vm3lbg",
"title": "Fashion"
}
]
},
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iqg",
"title": "Business"
},
"subcategories": [
{
"documentId": "c8kr3d7012vtr8vm3jjg",
"title": "Crypto"
},
{
"documentId": "c8kr3d7012vtr8vm3jj0",
"title": "Finance"
},
{
"documentId": "c8kr3d7012vtr8vm3jkg",
"title": "Marketing"
}
]
}
]
}
I have tagview in my mobile screen so user can select multiple subcategory at a same time by select deselect so if i choose 2 subcategory from Art and 2 from Business then expected post payload should be like below
{
"data": [
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
}
So my code is like below
const tempDefaultPayload = dataPayload.map(x => {
if (x.category) {
x.subcategories?.push(subcategory);
if (userData?.userInterests?.map(v => v.category.documentId === category)) {
const arrayNewData: any = [];
const newData: any = userData?.userInterests?.map(i =>
i.subcategories?.map(k => {
arrayNewData.push(k?.documentId);
return k?.documentId;
}),
);
x.subcategories?.push(...arrayNewData);
}
return x;
}
return x;
})
When I run above code payload is not passing correct
[
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
It is passing all selected subcategory in both array any idea how can I solve this ?
If you have the selected tag ids in the array selectedTags and your json as a variable called data:
const tempDefaultPayload = {
data: data.data.map(x => {
"category": x.category.documentId,
"subcategories": x.subcategories.map(subcat =>
subcat.documentId).filter(item => selectedTags.includes(item))
})
}
Playground example

transform a js object using reduce

I want to write a function that transfers this object
[
{
"id": "656DDXFT565xX",
"name": "Black item",
"categorues": [
"Black",
"White"
],
"price": 5
}
]
to be like a thing like that
[
{
"Black": [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categories": [
"Black",
"White"
],
"price": 5
}
]
},
{
"White": [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categories": [
"Black",
"White"
],
"price": 5
}
]
}
]
I tried with Array.reduce, but I don't know how to render this.
If anyone has any hindsight on this
You can iterate over the categorues of each item using .map to get the expected result. This a solution using lodash:
const data = [
{ "id":"656DDXFT565xX", "name":"Colored item", "categorues":["Black","White"], "price":5 },
{ "id":"656DDXFT565x2", "name":"White item", "categorues":["White"], "price":5 },
{ "id":"656DDXFT565x3", "name":"Black item", "categorues":["Black"], "price":5 }
];
const _reduceElem = (elem={}) => {
const { categorues=[] } = elem;
return _.map( categorues, cat => ({ [cat]: [_.cloneDeep(elem)] }) );
}
const res = _.reduce(data, (acc,item) => {
acc = [...acc, ..._reduceElem(item)];
return acc;
}, []);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
let before = [
{
"id": "656DDXFT565xX-BW",
"name": "Black and white item",
"categories": [
"Black",
"White"
],
"price": 5
},
{
"id": "656DDXFT565xX-K",
"name": "Black item",
"categories": [
"Black"
],
"price": 10
},
{
"id": "656DDXFT565xX-W",
"name": "White item",
"categories": [
"White"
],
"price": 15
}
]
let after = before.reduce(
(acc, val) => {
val.categories.forEach(cat => {
acc[cat] ||= []
// if this fails, use newer version of node, or use
// if(!acc.cat) acc.cat = []
acc[cat].push(val)
})
return acc
},
{}
)
console.log(after)
Since you just want to extract categorues as a key. You don't need to use reduce, just using map to loop the categorues is fine.
const origin = [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categorues": [
"Black",
"White"
],
"price": 5
}
]
const categorues = origin[0].categorues;
const result = categorues.map(item => {
return {
[item]: origin
}
})
console.log(result)

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);

Massaging JSON Data with underscore.js

I have stored the data in the following manner
[
{
"metadata": {
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
},
"entityTitle": "Opportunities"
},
{
"metadata": {
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
},
"entityTitle": "Reports"
}
]
I need to transform this into :
[
{
"entityTitle": "Opportunities",
"searchResults": [
{
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
}
]
},
{
"entityTitle": "Reports",
"searchResults": [
{
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
}
]
}
]
I have used _.groupBy , like this
_.groupBy(recentData, function(data) {
return data.entityTitle;
});
and I got :
{
"Opportunities": [
{
"metadata": {
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
},
"entityTitle": "Opportunities"
}
],
"Reports": [
{
"metadata": {
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
},
"entityTitle": "Reports"
}
]
}
I need to store the recently searched data into an array, so I am storing the data like this.Can anyone help please me get the data into proper format?
Just a simple mapping will suffice:
const data = [
{
"metadata": {
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
},
"entityTitle": "Opportunities"
},
{
"metadata": {
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
},
"entityTitle": "Reports"
}
];
const transformation = data.map( item => ({
"entityTitle": item.entityTitle,
"searchResults": [
item.metadata
]
}));
console.log( transformation );
But I would advice against storing the search results this way.
I would store the current search results in a seperate array and just have the indexes of the entity inside the entities array, so that there's a clear seperation between the searches and the entities, since the entity should not care about if it's being searched or not.
In case there's multiple entities of the same name, we can replace the mapping by a reduction:
const data = [
{
"metadata": {
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
},
"entityTitle": "Opportunities"
},
{
"metadata": {
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
},
"entityTitle": "Reports"
},
{
"metadata": {
"subtitle": "kat",
"id": "0045100000yCqRfAAK",
"title": "#98640100"
},
"entityTitle": "Opportunities"
}
];
const transformation = Object.values(
data.reduce(( groups, item ) => {
const entityTitle = item.entityTitle;
if ( !groups[ entityTitle ] ) groups[ entityTitle ] = { entityTitle, "searchResults": [] };
groups[ entityTitle ].searchResults.push( item.metadata );
return groups;
}, {} )
);
console.log( transformation );
Use a chain and map the groups created by _groupBy. The search results within each group also need mapping to remove the metadata property
let res =
_.chain(data)
.groupBy('entityTitle')
.map(function(results, title) {
return {entityTitle: title, searchResults: _.map(results, 'metadata') };
})
.value();
console.log(res)
.as-console-wrapper {
max-height: 100%!important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js">
</script>
<script>
data = [{
"metadata": {
"subtitle": "kit",
"id": "0063400000yCqRfAAK",
"title": "#9864478"
},
"entityTitle": "Opportunities"
},
{
"metadata": {
"subtitle": "foo",
"id": "foo",
"title": "#foo"
},
"entityTitle": "Opportunities"
},
{
"metadata": {
"subtitle": "Acceleration",
"id": "0063400000yCqRfAAK",
"title": "#9882278"
},
"entityTitle": "Reports"
}
]
</script>

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);
}

Categories

Resources