I have an HTML page that contains a stringified JSON object. The object has this structure:
{
"x":{
"key1":[],
"key2":{},
"keyN":{},
"myKey":{
"randomID238492":{
"items":[
{ "value":"zzzz" },
{ "value":"aaaa" },
{ ...}
]
}
}
}
}
I want to replace this object with one in which the "items" array has been sorted. Here is what I will and won't know about the object:
"myKey" and "items" will always be the relevant object keys
"myKey" will contain only one random ID, and the "items" key will always be its first child
I won't know the order of "myKey" in the object.
I won't know the true randomID under which "items" nests.
Is there a clear, efficient way to replace this JSON object with one in which "items" has been sorted? Right now, I do it by using this jQuery function after the page has rendered:
$(function() {
var myData = $( "#myJSON_string" )[0]; // <script> node that contains the string
var myDataJSON = JSON.parse(myData.innerText); // JSON string
var myKeyJSON = myDataJSON["x"]["myKey"]; // object
var myArr = myKeyJSON[Object.keys(myKeyJSON)[0]]["items"]; // array to sort
// Now sort and revise. I'm leaving myCompare() out of the example for brevity
myKeyJSON[Object.keys(myKeyJSON)[0]]["items"] = myArr.sort(myCompare);
myDataJSON["x"]["myKey"] = myKeyJSON;
myDataJSON = JSON.stringify(myDataJSON);
myData.innerText = myDataJSON;
});
This approach works, but it seems rather labored. It might be better, for example, if I could revise the JSON object "in place" without parsing it and then re-stringifying it.
Many SO posts, like this one, speak to the general question of how to sort a JSON array. But I can't see that any speak to the specific question posed here.
Related
I have a JSON data set as follows:
{
"content":[],
"layout":[],
"trail":[
{
"content":[
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":593,
"height":900,
"url":"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877",
"flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"
}
}
]
},
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":1600,
"height":900,
"url":"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532",
"flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"
}
}
]
}
],
"colors":{
"c0":"#1e1e1d",
"c1":"#78736f",
"c2":"#b2a89f"
}
}
]
}
I would like to console.log the "url" key for each of the images shown here.
(https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg and https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg)
I tried some code but I'm very new to JSON in general, I've looked at some other answers to do with JSON but I'm not quite sure how to achieve what I want.
JSFiddle: https://jsfiddle.net/fj6qveh1/1/
I appreciate all advice, including links to other answers that I potentially missed.
Thank you!
url is a property of an object. There can be many of these in a media array. (This data only shows one object per array.) media itself is an property of objects inside the content array.
Use map, and flatMap.
map to return the URL values from the objects in media, and flatMap to return a flat array of the nested arrays returned by map.
const data={content:[],layout:[],trail:[{content:[{type:"image",media:[{type:"image/jpg",width:593,height:900,url:"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877","flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"}}]},{type:"image",media:[{type:"image/jpg",width:1600,height:900,url:"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}},{type:"image/jpg",width:1600,height:900,url:"https://live.dummyimage.com/2817/dummy.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}}]}],colors:{c0:"#1e1e1d",c1:"#78736f",c2:"#b2a89f"}}]};
const content = data.trail[0].content;
const urls = content.flatMap(obj => {
return obj.media.map(inner => inner.url);
});
console.log(urls)
The easiest way is to use map function. Given that you are very new to programming (the solution has little to do with JSON itself, since the first step is to parse JSON string to a JavaScript object), it would be better if you try yourself. But you start with
let urls = trail["content"].map(x => x["media"][0]["url"])
for more about map function look here
There is a table in the table so for each table:
for(let i in trail){
var content = trail[i]["content"];
content.forEach(content => content.media.forEach(media => console.log(media.url)))
}
To access object properties, you can use a dot (.), and to access an array element, you use its index in square brackets ([]). So you just keep repeating these steps as necessary until you get to the content you're looking for.
Here's how that looks on a simplified version of your object, using the forEach method of arrays to apply a custom function to each item in the content array:
const json = getJson();
json.trail[0].content.forEach(item=>console.log(item.media[0].url));
function getJson(){
let obj = {
"trail": [{
"content": [
{ "media": [{ "url":"image #65535/48208920877_e6b234d3ea_c_d.jpg" }]},
{ "media": [{"url":"image #2817/33807326532_91013ef6b1_h_d.jpg"}]}
]
}]
};
return obj;
}
I have a languages array. I need to insert my array data into Json Objeatc within a function.
I am a new student and I tried to do this using map. But it only inserts one data of array into a JSON object. But I need to insert all off array data one by one. But I don't know the way to that.IF anyone can help me with that it's really mean to me. Thank you.
This is how I need to be my JSON object:-
"displayNameLocalization": {
"en": "Fruits",
"fr": "des fruits",
"ja": "果物"
}
const data = {
displayNameLocalization : {},
};
const languages = ['En', 'Ta', 'Fr'];
function testFinalValue() {
displayNameLocalization.map((item) => {
data.displayName = item;
});
}
that's because you are overwritten the same variable in each loop of map, because there will be one element in data with name displayName , so in each loop you are affecting w new value to the same element that's why you input has just one value affected.
Can you afford an example of the input and the output that you want to get so I can help you with the code.
I want to merge two object using JavaScript
First
{
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
}
second
{
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"]
}
and form a single object:
expected output
{
"user" : "Hari"
"friend" : "Shiva",
"friendList":[
["Hanks"," Tom","Karma"," Hari"," Dinesh"],
["Karma"," Tom"," Ram"," Bindu"," Shiva"," Kishna"," Bikash"," Bakshi"," Dinesh"]
]
}
Is it possible? I am sorry if it is wrong question....but I need to solve in this way and I do not have much idea about JavaScript.
You can add from one array to anther like this
var a={
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
};
var b={
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"]
};
b.friendList.concat(a.friendList);
you will get on b all the array of a+b...
you will not get this structure that you want. For my code you will get an array of strings from a and b, if you want this structure you need to change the result to be an object and not array.
also can see example from : link
The following code will merge the objects as described in your question:
var firstObject = {
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
};
var secondObject = {
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"],
};
function mergeMyObjectsIntoNew(first,second,copyFriendListArrayReference){
//.trim() is needed in the compare here because example data has a leading space
// in secondObject.friend
if(first.user.trim() === second.user.trim()
&& first.friend.trim() === second.friend.trim()){
var newObject={}; //The new object
newObject.user = first.user;
newObject.friend = first.friend;
newObject.friendList = []; //Create new array
if(copyFriendListArrayReference){
//This copies references for the arrays in first.friendList and
// second.friendList into the array new.friendList. These will be the
// same arrays as exists in first and second. Changes to the contents
// of those arrays will affect the arrays in the newObject.
newObject.friendList[0] = first.friendList; //add friendList from first
newObject.friendList[1] = second.friendList; //add friendList from second
}else{
//This copies the string contents of the arrays in first.friendList and
// second.friendList into the array new.friendList. These will NOT be the
// same arrays as exists in first and second. Changes to the contents
// of those arrays will NOT affect the arrays in the newObject.
// This is the default behavior.
//Copy contents of friendList from first
newObject.friendList[0] = Array.from(first.friendList);
//Copy contents of friendList from second
newObject.friendList[1] = Array.from(second.friendList);
}
return newObject;
}//implicit else due to 'return' in all if paths
return null; //Indicate to caller that there was not a match.
}
//Get new merged object with copy of friendList
mergedObject = mergeMyObjectsIntoNew(firstObject,secondObject);
console.log(mergedObject);
Comments
Using multiple very similarly structured objects is, often, a bad idea
It is, generally, not a good idea to use objects that have two different structures, unless you are keeping those objects distinctly separate. When you do have multiple structures for objects which you treat similarly (i.e. you use the same functions/methods to manipulate objects with both structures), all of your code has to account for each of the multiple structures. This can rapidly make your code much more complex and, potentially, more confusing than it would need to be if you did not have multiple structures for objects which you treat similarly.
In this case, you are wanting your result object to have a friendList property which is an array of arrays of strings whereas your source objects have a friendList property which is an array of strings. If you are going to use mergeMyObjectsIntoNew on both object structures, having the two different structures for the friendList property would require more logic in mergeMyObjectsIntoNew, if you want it to be able to operate on both types of object with the results you would, probably, expect.
For instance, the following code will not produce the result that you are probably expecting:
mergedFirstSecondObject = mergeMyObjectsIntoNew(firstObject,secondObject);
mergedthirdFourthObject = mergeMyObjectsIntoNew(firstObject,secondObject);
mergedFourObjects = mergeMyObjectsIntoNew(mergedFirstSecondObject,mergedthirdFourthObject);
This will produce an object that has a friendList property that is an array of arrays of arrays of strings. The mergedFourObjects object is structured like:
{
"user" : " Hari",
"friend" : "Shiva",
"friendList": [
[
friendListArrayFromFirstObject,
friendListArrayFromSecondObject
],
[
friendListArrayFromThirdObject,
friendListArrayFromFourthObject
]
]
}
In your case, you are probably better off picking to always have the friendList property be only one or the other of an array of array of strings, or an array of strings. Having the friendList property such that it might be either structure will significantly complicate your code everywhere you use these objects.
Using a class would be the better approach to handling your objects
If you are going to be using your objects in a larger project, it is probably a better idea to use a class for the object. This would allow you to move things like comparing the objects and merging the objects into methods of the class (e.g. MyObject.prototype.compare(second) and MyObject.prototype.merge(second). However, that is a discussion well beyond the scope of your question. If you want more information, I suggest you search for information about using object classes in JavaScript.
I am trying to sort every Array by Name in an JSON-Object using Node.js.
I manage to sort just the Array with Underscore.js, but how can I input the whole Object and just get the Object back finished sorted?
Thinking about looking through the object recursively for Arrays and sort every one of them, but how can I do that?
Here is an example Object with just sorting the Array:
var _ = require("./underscore.js")
var jsonObject = { "Configuration":{
"$":{
"xmlns":"http://www.example.com/"
},
"ApplicationInstance":{
"Description":"Description text here.",
"Name":"Server1",
"Class":"System",
"Visibility":"System",
"CustomerCreated":"0",
"Active":"0",
"IntroducedIn":{
"$":{
"xsi:nil":"true",
"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"
}
},
"Property":[
{
"Description":"JMS publisher destination type.",
"Name":"jmsJBossPublisher.destinationType",
"Class":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"QUEUE",
"AttributeDataTypeName":"String"
},
{
"Description":"jmsConnectionFactory properties.",
"Name":"jmsConnectionFactory.jndiNameForJmsConnectionFactory",
"SecurityClass":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"ConnectionFactory",
"AttributeDataTypeName":"String"
}
],
"ServerId":"1",
"ApplicationName":"ActivityGateway",
"InstanceID":"1"
}
}
};
console.log(_.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name'))
_.sortBy returns a cloned array, so you'll need to override the previous value.
Try adding this line:
jsonObject.Configuration.ApplicationInstance.Property = _.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name')
so I have a JSON object returned from a webservice. Now I want to:
get a subset which matches a categoryTitle i pass as parameter (this seems to work)
from my filtered resultset I want to get another array of objects (helpsubjects), and for each of this subjects I want to extract the SubjectTitle.
Problem: It seems my Array of HelpSubjects does not exist, but I can't figure out why and hope you could help.
Perhaps this piece of commented code makes it more clear:
$.fn.helpTopicMenu = function (data) {
that = this;
var categoryContent = contents.filter(function (el) {
return el.CategoryTitle == data.categoryTitle;
});
debug('categorys Content: ', categoryContent); //see below
var container = $('#subjectList');
var subjectList = categoryContent.HelpSubjects;
debug('Subjects in Category: ', subjectList); // UNDEFINED?!
$.each(subjectList, function (i, item) {
container.append(
$('<li></li>').html(subjectList[i].SubjectTitle)
);
});
the line debug('categorys Content: ', categoryContent); returns the following object as shown in the picutre (sadly I can't add a picture directly to the post yet, so here's the link): http://i.stack.imgur.com/0kKWx.png
so as I understand it, there IS actually a HelpSubjects-Array, each entry containing a SubjectTitle (in the picture there actually is only one entry, but I need to have the Artikel einfügen as my html.
Would be great if you can help me.
The variable categoryContent set is an array of objects.
Try debugging categoryContent[0].HelpSubjects and see if you can access the property. If so, you can also loop this array if need be.