This question already has answers here:
How can I access object properties containing special characters?
(2 answers)
Closed 5 years ago.
I have this URL which returns me a JSON value, my task is to access 3 values out of it that is name, title and ISBN.
Since the content is heavily nested, I am not able to access the values inside it.
All the tutorials I have referred so far, have simple nesting in them
I have attached my code that I have written so far:
$(document).ready(function() {
var globalJsonVar;
alert("check");
$.getJSON("https://openlibrary.org/api/books?bibkeys=ISBN:9781606868829&jscmd=details&format=json", function(result) {
if (Object.keys(result).length > 0) {
alert("conetnt is present");
console.log(result);
alert(Object.values(result));
alert(result.ISBN: 9781606868829. bib_key); // my attempt at accessing the values
} else {
alert("hoax");
}
});
});
The JSON content that I am receiving is
{
"ISBN:9780143039648": {
"bib_key": "ISBN:9780143039648",
"preview": "noview",
"preview_url": "https://openlibrary.org/books/OL17924003M/The_guide",
"info_url": "https://openlibrary.org/books/OL17924003M/The_guide",
"details": {
"number_of_pages": 196,
"series": [
"Penguin classics"
],
"lc_classifications": [
"PR9499.3.N3 G85 2006"
],
"latest_revision": 7,
"uri_descriptions": [
"Contributor biographical information",
"Publisher description"
],
"genres": [
"Fiction."
],
"title": "The guide",
"languages": [{
"key": "/languages/eng"
}],
"subjects": [
"Malgudi (India : Imaginary place) -- Fiction.",
"Tour guides (Persons) -- Fiction.",
"Bharata natyam dancers -- Fiction.",
"Spiritual life -- Hinduism -- Fiction.",
"India -- Fiction."
],
"publish_country": "nyu",
"by_statement": "R.K. Narayan ; introduction by Michael Gorra.",
"type": {
"key": "/type/edition"
},
"uris": [
"http://www.loc.gov/catdir/enhancements/fy0716/2006044314-b.html",
"http://www.loc.gov/catdir/enhancements/fy0716/2006044314-d.html"
],
"revision": 7,
"publishers": [
"Penguin Books"
],
"dewey_decimal_class": [
"823/.914"
],
"last_modified": {
"type": "/type/datetime",
"value": "2012-08-05T21:10:58.887826"
},
"key": "/books/OL17924003M",
"authors": [{
"name": "Rasipuram Krishnaswamy Narayan",
"key": "/authors/OL5911201A"
}],
"publish_places": [
"New York"
],
"oclc_number": [
"65644730"
],
"pagination": "xxiv, 196 p. ;",
"created": {
"type": "/type/datetime",
"value": "2008-10-07T19:30:19.584308"
},
"url": [
"http://www.loc.gov/catdir/enhancements/fy0716/2006044314-b.html",
"http://www.loc.gov/catdir/enhancements/fy0716/2006044314-d.html"
],
"notes": {
"type": "/type/text",
"value": "Originally published: New York : Viking Press, 1958.\n\nIncludes bibliographical references (p. [xxi]-xxii)."
},
"identifiers": {
"goodreads": [
"129877"
],
"librarything": [
"6930"
]
},
"isbn_13": [
"9780143039648"
],
"lccn": [
"2006044314"
],
"isbn_10": [
"0143039644"
],
"publish_date": "2006",
"works": [{
"key": "/works/OL1057183W"
}]
}
}
}
You have to use [] if you want to have access to keys that have special chars, for example result['something-with:special-chars']
result.ISBN:9781606868829.bib_key
is a syntax error. : is not allowed here. You want to use the following syntay :
result["ISBN:9781606868829"].bib_key
Related
Ok, this one might be a doozy. I'm banging away but wonder if there's an elegant way to approach this.
I have an object of assets, each of which has some properties, as well as some number of sub-assets in either of two possible objects: assets and characteristics.
I also have a flat object with the defaults for each type of asset stored.
I would like to iterate through the object, detect the type of asset I'm looking at from the ID, load the properties from the flat defaults object, overwrite any of those that's present in the nested object, and return a new nested object that's got all the defaults, but is also updated with anything present in the original nested object.
For example, the nested object:
{
"id": "Bohemian Rhapsody",
"version": "0.10.1.5",
"manifest": "6s43qhuy53as980u08647ugp864q867-08d4svbn9uh54xc8vu",
"slug": "DarkShiftingBolt",
"visibility": "friends",
"locked": true,
"values": {"value0":2},
"assets": [
{
"id": "I see",
"assets": [
{
"id": "a little",
"name": "Queen",
"values": {
"value1": 1,
"value2": 3,
"value3": 2
},
"characteristics": [
{
"id": "silhouetto",
"assets": [
{
"id": "of a man",
"values": {
"value4": 3,
"value5": 1
},
"assets": [
{"id": "Scaramouche"}
]
}
]
}
],
"assets": [
{"id": "Scaramouche"}
]
},
{
"id": "will you",
"name": "Freddy",
"values": {
"value1": 1,
"value2": 0,
"value3": 3
},
"assets": [
{
"id": "do the",
"assets": [
{"id": "fandango"}
]
}
]
}
]
}
]
}
The flat defaults object:
{
"Bohemian Rhapsody": {
"visibility": "hidden",
"locked": false,
"values": {"value0":1},
},
"I see": {
"cost": 4
},
"a little": {
"values": {
"value2": 1,
"value4": 5
},
},
"silhouetto": {
"cost": 1
},
"of a man": {
"genre": "opera"
},
"Scaramouche": {
"rank": 3
},
"will you": {
"values": {
"value4": 0
},
},
"do the": {
"signature": [[4,4],[2,4],[6,8]]
},
"fandango": {
"records": ["thunderbolts","lightning"]
}
}
The desired output object:
{
"id": "Bohemian Rhapsody",
"version": "0.10.1.5",
"manifest": "6s43qhuy53as980u08647ugp864q867-08d4svbn9uh54xc8vu",
"slug": "DarkShiftingBolt",
"visibility": "hidden",
"locked": false,
"values": {"value0":1},
"assets": [
{
"id": "I see",
"cost": 4,
"assets": [
{
"id": "a little",
"name": "Queen",
"values": {
"value1": 1,
"value2": 1,
"value3": 2,
"value4": 5
},
"characteristics": [
{
"id": "silhouetto",
"assets": [
{
"id": "of a man",
"genre": "opera",
"values": {
"value4": 3,
"value5": 1
},
"assets": [
{
"id": "Scaramouche",
"rank": 3
}
]
}
]
}
],
"assets": [
{
"id": "Scaramouche",
"rank": 3
}
]
},
{
"id": "will you",
"name": "Freddy",
"values": {
"value1": 1,
"value2": 0,
"value3": 3,
"value4": 0
},
"assets": [
{
"id": "do the",
"signature": [[4,4],[2,4],[6,8]],
"assets": [
{
"id": "fandango",
"records": ["thunderbolts","lightning"]
}
]
}
]
}
]
}
]
}
What I'm trying is an object.keys recursive function that builds a new object from the properties it finds. I'm curious to know if there's a smarter way to go about it.
Got it thanks to #rayhatfield.
import * as merge from 'deepmerge';
this.manifest = (manifestData as any).default;
this.list = (listData as any).default;
this.list = this.assetIterate(this.list);
assetIterate(asset){
let id = asset.id;
let type = this.manifest.asset_catalog[id].type;
let newAsset = merge.all([this.manifest.asset_taxonomy[type],this.manifest.asset_catalog[id],asset])
Object.keys(asset).forEach((key) => {
if(key === "characteristics" || key === "assets"){
newAsset[key] = [...asset[key]]
newAsset[key].forEach((asset,index) => {
newAsset[key][index] = this.assetIterate(asset);
});
}
});
asset = {...newAsset}
return asset
}
Seems to work for all cases except a corner case in which a sub array needs to have indices replaced instead of concatenated, but I can special-case that when I actually make one of those.
I have a large JSON payload and I want to format, the specific object of the payload using JS.
I want flightdetails array object to edit and remove the special characters from it. How can I achieve this?
I have been working on this using XSLT for the past 2 days, and I went nowhere hence I decided to remove it using JS.
Example of the array(there can be more than 30 records inside the flightdetails)
"flightdetails": [
{
"id": XF-2092,
"trips": 2,
"categories": {
"flights": [
"\"return\",\"oneway\""
]
},
"id": XF-2093,
"trips": 1,
"categories": {
"flights": [
"\"return\""
]
}
}
]
Expected Output
"flightdetails": [
{
"id": XF-2092,
"trips": 2,
"categories": {
"flights": [
"return","oneway"
]
},
"id": XF-2093,
"trips": 1,
"categories": {
"flights": [
"return"
]
}
}
]
The flightdetails object inside the //destinations/flightdetails path
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'm Pearson's dictionary api. Here is an example of what I get back from an api call:
{
"status": 200,
"offset": 0,
"limit": 10,
"count": 10,
"total": 135,
"url": "/v2/dictionaries/entries?headword=dog",
"results": [
{
"datasets": [
"lasde",
"dictionary"
],
"headword": "dog",
"homnum": 2,
"id": "cqAFksnRpT",
"part_of_speech": "verb",
"senses": [
{
"definition": [
"if a problem dogs you, it causes trouble for a long time"
]
}
],
"url": "/v2/dictionaries/entries/cqAFksnRpT"
},
{
"datasets": [
"ldec",
"dictionary"
],
"headword": "dogged",
"id": "cqAJ3cApA5",
"part_of_speech": "adjective",
"senses": [
{
"translation": "堅持不懈的,頑強的,不屈不撓的"
}
],
"url": "/v2/dictionaries/entries/cqAJ3cApA5"
},
{
"datasets": [
"laad3",
"dictionary"
],
"headword": "dog",
"homnum": 1,
"id": "cs1sPF57rs",
"part_of_speech": "noun",
"senses": [
{
"definition": "a very common animal with four legs that is often kept as a pet or used for guarding buildings",
"examples": [
{
"text": "I could hear a dog barking."
}
]
}
],
"url": "/v2/dictionaries/entries/cs1sPF57rs"
},
{
"datasets": [
"laes",
"dictionary"
],
"headword": "dog",
"id": "csTMcVNVB7",
"part_of_speech": "verb",
"senses": [
{
"definition": [
"if a problem or bad luck dogs you, it continues to causes trouble for a long time"
],
"translations": [
{
"example": [
{
"text": "Funding problems have dogged the project from the start.",
"translation": {
"text": [
"Los problemas de financiación han marcado el proyecto desde su inicio."
]
}
}
],
"full_form_tran": [
"mala suerte, problemas"
],
"text": [
"perseguir"
]
}
]
}
],
"url": "/v2/dictionaries/entries/csTMcVNVB7"
},
{
"datasets": [
"brep",
"dictionary"
],
"headword": "dogged",
"id": "ct59x9PnK6",
"part_of_speech": "adjective",
"pronunciations": [
{
"ipa": "ˈdɔgɪd",
"lang": "American English"
}
],
"senses": [
{
"translations": [
{
"example": [
{
"text": "She got there through sheer dogged determination to succeed.",
"translation": {
"text": [
"Ela chegou lá somente por uma determinação obstinada de ter sucesso."
]
}
}
],
"text": [
"obstinado"
]
}
]
}
],
"url": "/v2/dictionaries/entries/ct59x9PnK6"
},
{
"datasets": [
"laes",
"dictionary"
],
"headword": "doggedly",
"id": "csTMcVNjmK",
"part_of_speech": "adverb",
"pronunciations": [
{
"ipa": "ˈdɔgɪdli"
}
],
"senses": [
{
"definition": [
"in a way that shows you are determined to achieve something or continue doing something despite difficulties"
],
"translations": [
{
"example": [
{
"text": "He spent the next two years doggedly following his plan.",
"translation": {
"text": [
"Pasó los dos años siguientes apegado obstinadamente a su plan."
]
}
}
],
"text": [
"con tenacidad"
]
}
]
}
],
"url": "/v2/dictionaries/entries/csTMcVNjmK"
},
{
"datasets": [
"ldoce5",
"dictionary"
],
"headword": "dog",
"homnum": 2,
"id": "cqAFAggc8c",
"part_of_speech": "verb",
"senses": [
{
"definition": [
"if a problem or bad luck dogs you, it causes trouble for a long time"
],
"examples": [
{
"audio": [
{
"type": "example",
"url": "/v2/dictionaries/assets/ldoce/exa_pron/p008-000811030.mp3"
}
],
"text": "He has been dogged by injury all season."
}
]
}
],
"url": "/v2/dictionaries/entries/cqAFAggc8c"
},
{
"datasets": [
"lasde",
"dictionary"
],
"headword": "dog",
"homnum": 1,
"id": "cqAFksYTtm",
"part_of_speech": "noun",
"pronunciations": [
{
"ipa": "dɒg"
},
{
"ipa": "dɒːg",
"lang": "American English"
}
],
"senses": [
{
"cross_references": [
{
"headword": "pet",
"homnum": 1,
"url": "/v2/dictionaries/entries/cqAFxHe1mp"
}
],
"definition": [
"a very common animal with four legs, fur, and a tail. Dogs are often kept as pets or as working animals."
],
"examples": [
{
"text": "I could hear a dog barking."
}
],
"related_words": [
"puppy"
]
}
],
"url": "/v2/dictionaries/entries/cqAFksYTtm"
},
{
"datasets": [
"laad3",
"dictionary"
],
"headword": "dogged",
"id": "cs1sPG5Mck",
"part_of_speech": "adjective",
"senses": [
{
"definition": "dogged actions or behavior show that you are very determined to continue doing something",
"examples": [
{
"text": "a dogged determination to succeed"
}
]
}
],
"url": "/v2/dictionaries/entries/cs1sPG5Mck"
},
{
"datasets": [
"leasd",
"dictionary"
],
"headword": "dog",
"id": "crzpqPP3Zh",
"part_of_speech": "noun",
"senses": [
{
"definition": "huisdier",
"translations": [
{
"text": "hond"
}
]
}
],
"url": "/v2/dictionaries/entries/crzpqPP3Zh"
}
]
}
As you can see, the "results" array returns an array of objects. I want insert each part of each object in my DOM, but each object doesn't have the same keys. Some objects have a translation, while some have a definition. Some nested keys even have arrays. Is there a function I can write to catch all the keys in each object and return all the info?
I'm assuming that you have used JSON.parse() (or other methodology) to get an actual Object instead of the JSON text that is in your question.
There are multiple ways that you can do this. I would suggest that you look at:
the various methods of Object. For example:
keys()
getOwnPropertyNames()
hasOwnProperty()
for...in
for...of
Array.prototype.forEach() (e.g. in combo with keys())
typeof
There are really just too many ways to do what you are asking. We don't have enough information to be able to actually suggest a "good" method of doing what you desire. The easiest way may be to use a JavaScript module that does a mapping of an object/JSON to HTML. It really depends on what you are actually wanting to end up with.
If you are manually putting the information in your DOM, you could, for instance, determine if you have a definition property, by doing:
if(obj.hasOwnPrperty('definition')) {
//Yes, it has the property
}else{
//No, it does not have the property
}
Basically I want to be able, in Javascript (JQuery optionally), to search into a JSON with nested elements for a particular element and edit it.
Ex. search for "components" with id 110 and change the name to "video card".
Notice the following JSON is just an example. I am wondering if javascript libraries or good tricks exist to do such a thing, I don't think traversing the whole json or writing my own methods is the best solution.
{
"computers": [
{
"id": 10,
"components": [
{
"id": 56,
"name": "processor"
},
{
"id": 24,
"name": "ram"
}
]
},
{
"id": 11,
"components": [
{
"id": 110,
"name": "graphic card"
},
{
"id": 322,
"name": "motherboard"
}
]
}
]
}
You could try linq.js.
You can use this javascript lib, DefiantJS (http://defiantjs.com), with which you can filter matches using XPath on JSON structures. To put it in JS code:
var data = {
"computers": [
{
"id": 10,
"components": [
{ "id": 56, "name": "processor" },
{ "id": 24, "name": "ram" }
]
},
{
"id": 11,
"components": [
{ "id": 110, "name": "graphic card" },
{ "id": 322, "name": "motherboard" }
]
}
]
},
res = JSON.search( data, '//components[id=110]' );
res[0].name = 'video card';
Here is a working fiddle;
http://jsfiddle.net/g8fZw/
DefiantJS extends the global object JSON with the method "search" and returns an array with matches (empty array if no matches were found). You can try out the lib and XPath queries using the XPath Evaluator here:
http://www.defiantjs.com/#xpath_evaluator