Given the following object graph:
{
"children": [{
"child": {
"pets": [{
"pet": {
"name": "fido"
}
},
{
"pet": {
"name": "fluffy"
}
}
]
}
},
{
"child": {
"pets": [{
"pet": {
"name": "spike"
}
}]
}
}
]
}
What would be a nice one-liner (or two) to collect the names of my grandchildren's pets? The result should be ["fido", "fluffy", "spike"]
I don't want to write custom methods for this... I'm looking for something like the way jQuery works in selecting dom nodes, where you can just give it a CSS-like path and it collects them up for you.
I would expect the expression path to look something like "children child pets pet name"
LINQ to JavaScript (JSLINQ) is an implementation of LINQ to Objects implemented in JavaScript. It is built using a set of extension methods built on top of the JavaScript Array object. If you are using an Array, you can use LINQ to JavaScript.
LINQ to JavaScript is an open source project and you can download it from here: http://jslinq.codeplex.com/
Hope this helps...
s
If you don't want to use a library, this is the most concise way I could think of writing it.
var Ar=[];
p.children.map(function(a){a.child.pets.map(function(a){Ar.push(a.pet.name)})});
I settled on the JSONPath library, which is like XPath for JSON. LINQ seemed a little heavyweight for my needs, resulting in a more verbose syntax, though it does look more powerful. Perhaps if my needs change I'll upgrade.
Related
This is my first post. I don't like ask help in forums, but I have no choice. I spent a lot of days trying resolve this but I haven't found any solution.
All my problem start with an database query that returns this.
{
"prod_format": "400 ml",
"prod_brand": "Marca",
"prod_image": "192.168.1.45/mini/1046332bb531ab3.jpg",
"prod_name": "Gel de baño o ducha",
"prod_pvp": 2.20,
"prod_shops": [
{
"prod_price": 2.29,
"prod_shop": {
"prod_shopID": 2,
"prod_shop_name": "Tienda",
"prod_shop_image": "192.168.1.45/shops/d4d4sw2.jpg"
}
},
{
"prod_price": 2.19,
"prod_shop": {
"prod_shopID": 5,
"prod_shop_name": "Tienda",
"prod_shop_image": "192.168.1.45/shops/g4hbe72.jpg"
}
}
]
}
I want remove prefixes of keys, prod_ and shop_ in this case.
I can't do this by hand because this is only one of multiple queries that i use, and this data can change, i need an dynamic function that remove these prefixes, to use with more prefixes and more queries.
So far I have been trying:
Recursive function that calls itself to remap inside objects and
arrays, but it doesn't work because NodeJS is asynchronous and make an
loop that never ends.
Use an list function that gets all keys/values to make a new object
with renamed keys, but i cant found anything that works with complex
objects.
Use chained promises, i can't get that it works, but i think that
it is the best way to do this.
In conclusion I want an function that if I put the upper object, I get this code.
{
"format": "400 ml",
"brand": "Marca",
"image": "http://192.168.1.45/mini/1046332bb531ab3.jpg",
"name": "Gel de baño o ducha",
"pvp": 2.20,
"shops": [
{
"price": 2.29,
"shop": {
"shopID": 2,
"name": "Tienda",
"image": "http://192.168.1.45/shops/d4d4sw2.jpg"
}
},
{
"price": 2.19,
"shop": {
"shopID": 5,
"name": "Tienda",
"image": "http://192.168.1.45/shops/g4hbe72.jpg"
}
}
]
}
PS:
I can't edit the original object, because it comes of elasticsearch and i can't edit object keys.
Thanks in advance, I hope that anyone can help me.
Why don't you simply treat your Json data as a string and then replace '"_prod' with '"'? That would remove all occurances of this prefix.
myJsonString.replace('"_prod', '"');
Update: If your values may contain your prefixes, you better use regular expressions instead, just to make sure you only change the keys.
I'm struggling to figure out if my method of listing objects in JSON is correct/efficient. I'm creating an API that will let the user search for engines in various ways and get info on them. So each "engine" object has several key/value pairs with it, and each "engine" is different. My current format is this:
{
"engines": [
{
"name": "Ford Modular Engine 3-valve",
"maker": "Ford",
"cam": "SOHC"
},
{
"name": "LS6",
"maker": "Chevy",
"cam": "OHV"
}
]
}
My concern with this format is accessing a specific engine as it is hidden under an array.
The other format idea I had was this (but I'm not sure if this is "proper" syntax for a JSON object)
{
"engines": {
"ford3v": {
"name": "Ford Modular Engine 3-valve",
"maker": "Ford",
"cam": "SOHC"
},
"ls6": {
"name": "LS6",
"maker": "Chevy",
"cam": "OHV"
}
}
}
Do the differences come down to personal preference? What is the industry standard?
In maximum cases option will be upto your requirement. It is better to have the following format because, it will be easy for you if you want to repeat the list in your html.
{
"engines": [
{
"name": "Ford Modular Engine 3-valve",
"maker": "Ford",
"cam": "SOHC"
},
{
"name": "LS6",
"maker": "Chevy",
"cam": "OHV"
}
]
}
I'd go with the first option, because your search API implies it'll be a list of engine objects coming back. With JSON, I tend to think of objects as key-value pairs for known properties, so it's more straightforward to iterate over a list and know to look for properties on those objects to do any filtering.
Not knowing the specific case you're writing this API for, I don't believe that consumers know to look for specific engines by the key/property you provide in the second example, especially if it's merely duplicating a field (name) already present in the object.
I have some data which I originally stored in a generic Javascript object, with the ID as a key:
{
"7": {"id":"7","name":"Hello"},
"3": {"id":"3","name":"World"},
...
}
However, I discovered that browsers do not guarantee a particular object order when looping through them, so in the above "3" would come before "7". I switched to using an array format like this:
[
{"id":"7","name":"Hello"},
{"id":"3","name":"World"},
...
]
Now, I can loop in the correct order but cannot do fast lookups, e.g. data["3"] without having to loop through the array.
Is there a good way to combine both approaches? I would rather avoid using a separate object for each format, because the object is pretty large (hundreds of elements).
I have run across this problem as well. A solution is to keep an ordered array of keys in addition to the original object.
var objects = {
"7": {"id":"7","name":"Hello"},
"3": {"id":"3","name":"World"},
...
}
var order = [ "3", "7", ... ];
Now if you want the second element you can do this lookup:
var second_object = objects[order[1]];
The ECMA standard does not say anything about the order of the elements in an object. And specifically Chrome reorders the keys when they look like numbers.
Example:
var example = {
"a": "a",
"b": "b",
"1": "1",
"2": "2"
};
if you print this in Chrome will get something like:
{
1: "1",
2: "2",
"a": "a",
"b": "b"
};
It's a little sour .. but life.
You could use the solution Andy linked as well, basically wrapping these two together in one object.
An alternative that I use a lot is a custom map function that allows you to specify the order in which the object is traversed. Typically you will do sorting when you're printing your data to the user so while you loop and create your table rows (for instance) your iterator will pass the rows in the order your sort function specifies. I thought it was a nice idea :)
The signature looks like:
function map(object, callback, sort_function);
Example usage:
map(object, function (row) {
table.add_row(row.header, row.value);
}, function (key1, key2) {
return object[key1] - object[key2];
});
Rather than coding your own, there are off-the-shelf libraries available to provide "as provided" JSON parsing or "consistently sorted" JSON printing for display.
You might well consider either of these:
The 'json-order' package offers parsing, formatting & pretty-printing with stable ordering. This is based on having ordered input.
The 'fast-json-stable-stringify' package offers deterministic formatting based on sorting.
I have the following json, I don't have any control over this output unfortunately.
{
"questions": {
"9733": {
"text": "Star Trek or Star Wars?",
"answers": {
"41003": "Star Trek",
"41004": "Star Wars",
"41005": "Neither is superior in my opinion; both great in their own ways",
"41006": "Not a fan",
"41007": "I don't have an opinion on this"
}
},
"25272": {
"text": "Which of these summer movies are you looking forward to the most?",
"answers": {
"99545": "World War Z",
"99546": "Monsters University ",
"99547": "White House Down",
"99548": "Man of Steel",
"99549": "Lone Ranger",
"99550": "The Wolverine"
}
},
"27547": {
"text": "Should the U.S. attack Syria?",
"answers": {
"107453": "Yes",
"107454": "No"
}
}
}
}
I am using json.parse to parse this. To get the text of the first question I would normally do something like this.
var jsonData = JSON.parse(data);//Where data = the json above
console.log(jsonData.questions.9733.text);//Obviously this fails
However javascript doesn't like that number in there obviously. How would you recommend accessing the text of the first question? I would prefer the json to be setup better with in an array of questions instead. Unfortunately I don't have any control over the output of this JSON.
I'm also not going to be aware of the what the keys are as they come across, but thats a whole other issue. I'm willing entertain any suggestions on how to parse this thing as I've never had to parse such a strange JSON output.
You need to use bracket notation:
console.log(jsonData.questions["9733"].text);
But because the value inside the brackets will be automatically converted a string, this would also work:
console.log(jsonData.questions[9733].text);
Note however, that using non-strings is as property names generally bad form and could lead to some subtle problems, e.g. if the property name was "001", then [001] would not work.
Why don't you try?
jsonData["questions"]["9733"]
How to access a numeric property?
I believe you can access the data via same syntax as in an array:
console.log(jsonData.questions[9733].text);
If you have to use numbers as keys... you can access them like this:
var text = jsonData.questions["9733"].text;
Edit: You can also access it with the number 9733. It doesn't have to be a string. Only needs to be a string if the key is non-numeric.
Try using Ason, If you are using Java 8. Gradle dependency compile 'org.arivu:ason:1.0.3'.
Java code as follows
Ason ason = new Ason();
Object json = ason.fromJson("<<JSON String!>>");
System.out.println(Ason.getJson(json, "questions.9733.text", null)):
I have an object like this:
var data = {
"info" : [{
"title": "Desemberkonsert",
"description": "MangerFHS 09/10"
}],
"playlist" : [
{
"title": "In This Place",
"description": "Excalibur",
"href": "desemberkonsert_in-this-place",
"url": "flv/desemberkonsert/21_in_this_place.flv",
"thumbnail": "flv/desemberkonsert/21_in_this_place_thumbnail.png",
"time": "5:39"
}]
}
And I am trying to do a search using jHashtables containsValue-function (I am willing to settle for any other search method that works though), like this containsValue(data.playlist, 'Excalibur'). But for some reason, this returns false. How would I select the array that contains the the value Excalibur from the code above?
I could not find a decent method inherently available in JavaScript or the jQuery library, but using a smaller library named jLinq (http://jlinq.hugoware.com/), doing it was a breeze. It allows me to filter with many different methods (I am using the 3.x beta though).
EDIT: The thing I missed was that the lowest arrays behave like objects too. But as Šime Vidas pointed out, I can select a subarray like this: data.playlist[0], and an item within that like this: data.playlist[0].description.