I am trying to display a button, only if a json object contains the element hidden: true
However, the child elements are random.
draw": { "item": { "aircraft": { "hidden": false} }
draw": { "item": { "mounted": { "hidden": false} }
I am ng-repeating on this json, and since I don't know if it is aircraft or mounted I can't do something like this
<button ng-if="json.draw.item.next.hidden" />
How can I say "Give me next element, without knowing the name"?
You can create a function like this:
function next(obj) {
var keys = Object.keys(obj);
if(keys && keys.length > 0) return obj[keys[0]];
}
To use it:
next(json.draw.item).hidden
I test it with Angular.js it is Ok.(see also jsFiddle)
See the snippet below.
function next(obj) {
var keys = Object.keys(obj);
if(keys && keys.length > 0) return obj[keys[0]];
}
var draw1 = { "item": { "aircraft": { "hidden": false} }};
var draw2 = { "item": { "mounted": { "hidden": false} }};
document.write(next(draw1.item).hidden, '<br>');
document.write(next(draw2.item).hidden, '<br>');
Related
I have been reading through many of the great code examples which test for the existence of object key in a object with arrays. These are great...
My problem is the JSON returned has key value that must be used to get to the items inside the array. Here is an example. Look at "orders":
{"Routes": [
{
"route": {
"id": "1daf1f53-80b6-49d6-847a-0ee8b814e784-20180821"
},
"vehicle": {
"id": "1daf1f53-80b6-49d6-847a-0ee8b814e784"
},
"driver": {
"id": "6c2823be-374e-49e5-9d99-2c3f586fc093"
},
"orders": {
"6df85e5f-c8bc-4290-a544-03d7895526b9": {
"id": "6df85e5f-c8bc-4290-a544-03d7895526b9",
"delivery": {
"customFields": {
"custom": "5379"
}
},
"isService": true
}
}
}
]
};
The code I am using works up to the point where I have to specify the key value:
function checkProperty(obj, prop) {
var parts = prop.split('.');
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i];
if (obj !== null && typeof obj === "object" && part in obj) {
obj = obj[part];
} else {
return false;
}
return true;
}
Here are some samples that work and fail:
console.log(checkProperty(test, 'Routes.0.orders')); //Works returns true
console.log(checkProperty(test, 'Routes.0.orders.id')); //Fails returns false
console.log(checkProperty(test, 'Routes.0.orders.6df85e5f-c8bc-4290-a544-03d7895526b9.id)); //Fails returns false
I am at my wits end and would appreciate any help...
"orders": {
"6df85e5f-c8bc-4290-a544-03d7895526b9": {
"id": "6df85e5f-c8bc-4290-a544-03d7895526b9"
second test:
Id is not a direct child of "Orders" in your example:
orders.6df85e5f-c8bc-4290-a544-03d7895526b9.id
third test:
syntax error in the third - missing '.'
I'm trying to modify a string with Typescript. The string is created by the JSON.stringify() method.
I want to remove the properties "id", "lightStatus" and the "value" attributes of "inputPort" and "outputPort". (I only need their attribute "id".)
console.log(JSON.stringify(this.light));
// Results in -> {"id":1,"name":"Light Switch","lightStatus":true,"inputPort":{"id":2,"value":0},"outputPort":{"id":2,"value":false},"resistance":100}
I tried to do it the following way but it doesn't recognize "inputPort.id" and "outputPort.id". This is what I tried and what it resulted in.
var savedLight = JSON.stringify(this.light, ["name", "inputPort.id", "outputPort.id", "resistance"]);
// Results in -> {"name":"Light Switch","resistance":100}
The result should include the properties "name", "inputPort id", "outputPort id" and "resistance". Like this:
{"name":"Light Switch","inputPort": 2, "outputPort": 2, "resistance":100}
Can anyone help me how I can get rid of the unnecessary properties?
You can pass a "replacer" function that returns the exact value you want.
var data = {"id":1,"name":"Light Switch","lightStatus":true,"inputPort":{"id":2,"value":0},"outputPort":{"id":2,"value":false},"resistance":100};
var result = JSON.stringify(data, function(k, v) {
switch (k) {
case "": case "name": case "resistance":
return v
case "inputPort": case "outputPort":
return v.id
default:
return undefined;
}
}, 2)
document.querySelector("pre").textContent = result
<pre></pre>
The "" represents the top level object. For that, "name", and "resistance", it simply returns the original value.
For "inputPort" and "outputPort" it returns the id property.
Anything else gets undefined, which means it gets omitted from the result.
You can use a replacer function for this.
var obj = {
"id": 1,
"name": "Light Switch",
"lightStatus": true,
"inputPort": {
"id": 2,
"value": 0
},
"outputPort": {
"id": 2,
"value": false
},
"resistance": 100
};
var stringified = JSON.stringify(obj, function(key, val) {
if (key === 'id' || key === 'lightStatus') {
return void(0);
}
if (key === 'inputPort' || key === 'outputPort') {
return val.id;
}
return val;
});
console.log(stringified);
You can apply Replacer function of JSON.stringify
var data='{"id":1,"name":"Light Switch","lightStatus":true,"inputPort":{"id":2,"value":0},"outputPort":{"id":2,"value":false},"resistance":100}';
var json=JSON.parse(data);
function replacer(i, val) {
switch (i) {
case "": case "name": case "resistance":
return val
case "inputPort": case "outputPort":
return val.id
default:
return undefined;
}
}
console.log(JSON.stringify(json,replacer));
I have this json file:
var data = [{
"id": 0,
"parentId": null,
"name": "Comapny",
"children": [
{
"id": 1235,
"parentId": 0,
"name": "Experiences",
"children": [
{
"id": 3333,
"parentId": 154,
"name": "Lifestyle",
"children": []
},
{
"id": 319291392,
"parentId": 318767104,
"name": "Other Experiences",
"children": []
}
]
}
]
}];
I need to find object by id. For example if need to find an object with id:319291392, I have to get:
{"id": 319291392,"parentId": 318767104,"name": "Other Experiences","children": []}
How can I do that?
I tried to use this function:
function findId(obj, id) {
if (obj.id == id) {
return obj;
}
if (obj.children) {
for (var i = 0; i < obj.children.length; i++) {
var found = findId(obj.children[i], id);
if (found) {
return found;
}
}
}
return false;
}
But it doesn't work as it's an array of objects.
If your starting point is an array, you want to invert your logic a bit, starting with the array rather than with the object:
function findId(array, id) {
var i, found, obj;
for (i = 0; i < array.length; ++i) {
obj = array[i];
if (obj.id == id) {
return obj;
}
if (obj.children) {
found = findId(obj.children, id);
if (found) {
return found;
}
}
}
return false; // <= You might consider null or undefined here
}
Then
var result = findId(data, 319291392);
...finds the object with id 319291392.
Live Example
This should work for you:-
var serachById = function (id,data) {
for (var i = 0; i < data.length; i++) {
if(id==data[i].id)
return data[i];
if(data[i].children.length>0)
return serachById(id,data[i].children);
};
return null;
}
console.log(serachById(0,data));
Here is another simple solution using object notation.
This solution will work even if you decide to get rid of teh array and use object notation later on. so the code will remain the same.
It will also support the case when you have element with no children.
function findId(obj, id) {
var current, index, reply;
// Use the object notation instead of index.
for (index in obj) {
current = obj[index];
if (current.id === id) {
return current;
}
reply = findId(current.children, id);
if (reply) {
return reply;
}
// If you reached this point nothing was found.
console.log('No match found');
}
}
console.log(findId(data, 319291392));
do it so:
for (var obj in arr) {
if(arr[obj].id== id) {
console.log(arr[obj]);
}
}
I have the following valid JSON. It describes a tree structure:
{
"items": [
{
"id": "d1"
},
{
"id": "2",
"children": [
{
"id": "3"
},
{
"id": "4"
},
{
"id": "5",
"children": [
{
"id": "6"
},
{
"id": "7",
"children": [
{
"id": "8"
},
{
"id": "9"
}
]
},
{
"id": "10"
}
]
},
{
"id": "11"
},
{
"id": "12"
}
]
},
{
"id": "13"
},
{
"id": "14"
}
]
}
I need to be able to get any of the "items" by id and any of the child items. For example. Initially I tried grep:
var returnedData = $.grep(obj.items, function(element, index){return element.id == "2";
});
This worked great for item with id==2 but fails completely when I try to obtain element.id=="7"
Any assistance would be appreciated. Thanks in advance.
You can make a recursive function to search in the data:
function find(source, id)
{
for (key in source)
{
var item = source[key];
if (item.id == id)
return item;
// Item not returned yet. Search its children by recursive call.
if (item.children)
{
var subresult = find(item.children, id);
// If the item was found in the subchildren, return it.
if (subresult)
return subresult;
}
}
// Nothing found yet? return null.
return null;
}
// In the root object, the array of items is called 'items', so we pass in
// data.items to look into. The root object itself doesn't seem to have an id anyway.
var result = find(data.items, 7);
// Show the name of item 7, if it had one...
alert(result.name);
Demo: http://jsfiddle.net/rj26H/
In this function I just looped over the object, so its a bit more verbose. You could probably also use $.grep to do the searching and make the code a bit smaller. Anyway, the trick is to search all children if the item is not found on the main level. Apparently grep doesn't work in a recursive fashion.
Try this:
var id = 7;
var data = {"items": [{"id": "d1"},{"id": "2","children": [{"id": "3"},{"id": "7"},{"id": "11"},{"id": "12"}]}]};
function search(values) {
$.each(values, function(i, v) {
if (v.id == id) {
console.log('found', v);
return false;
}
if (v.children) {
search(v.children);
}
});
}
search(data.items);
Demo Link
I know this have been already answered, but I wanted to show how you could leverage the new the new JavaScript 1.7 features to solve this. Please note that the same approach could have been used without support for generators, but the code would have been longer.
//Returns an iterator that knows how to walk a tree
function treeIterator(root, childGetter, childCountGetter) {
let stack = [root], node;
while (node = stack.pop()) {
yield node;
for (let i = childCountGetter(node); i--;) stack.push(childGetter(node, i));
}
}
//Our custom search function
function findNodeById(tree, id) {
let it = treeIterator(tree,
function (node, i) { return node.children[i]; },
function (node) { return node.children? node.children.length : 0; }
);
for (let node in it) if (node.id === id) return node;
return null;
}
var tree = {
id: 'root',
children: [
{ id: 'a' },
{
id: 'b',
children: [
{ id: 'b1' },
{ id: 'b2' }
]
},
{ id: 'c' }
]
};
findNodeById(tree, 'b1'); //Object { id="b1"}
Note that you can also set the __iterator__ on the data structure so that functions that needs to iterate over this data structure do not have to know implementation details.
tree.__iterator__ = treeIterator.bind(null, tree,
function (node, i) { return node.children[i]; },
function (node) { return node.children? node.children.length : 0; }
);
Then the findNodeById function can be:
function findNodeById(tree, id) {
for (let node in it) if (node.id === id) return node;
return null;
}
My Json array looks like this:
var data =
{
"categories":
{
"category1":
{
"Name": "Maps",
"Id": 3,
"orderInList": 1
},
"category2":
{
"Name": "Books",
"Id": 2,
"orderInList": 2
}
}
};
When I write do console.log(data), the 'key' to the object is formatted like:
| key | value |
categories[category1][Id] "3"
How can I iterate over this in a for loop (without using JQuery's $.each) so I can tell which key, value pairs are Names, Id's or orderInList's?
Working Jsfiddle
Something like this should work:
for (var category in data['categories']) {
for (var key in data['categories'][category]) {
var value = data['categories'][category][key];
// Now do whatever you want based on key...
switch (key) {
case 'Name':
// Whatever
break;
default:
break;
}
}
}
In any case, key and value in the inner loop will hold the key and value of your nested object, and category will hold the category.
The potentially confusing thing about this is that object properties can be accessed like array values in Javascript.
So consider the code below:
var some_object = {
a: 0
};
// These two lines do the same thing, even though some_object is not an array.
some_object.a = 1;
some_object['a'] = 1;
Your outer categories object is an object that contains many child objects. You can iterate through these children objects using a for...in loop.
for (var category in data.categories) {
// here you can access `category.Name`, `.Id`, and `.orderInList`
}
Checkout this
var data = {
"categories": {
"category1": {
"Name": "Maps",
"Id": 3,
"orderInList": 1
},
"category2": {
"Name": "Books",
"Id": 2,
"orderInList": 2
}
}
};
function represent(obj) {
var reprs = [];
for (var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
if (obj[key] instanceof Object) {
var result = represent(obj[key]);
for (var i = 0; i < result.length; i++) {
reprs.push("[" + key + "]" + result[i]);
}
}
else {
reprs.push("[" + key + "] = " + obj[key]);
}
}
return reprs;
}
console.log(represent(data));
//output
["[categories][category1][Name] = Maps",
"[categories][category1][Id] = 3",
"[categories][category1][orderInList] = 1",
"[categories][category2][Name] = Books",
"[categories][category2][Id] = 2",
"[categories][category2][orderInList] = 2"]
which key, value pairs are Names, Id's or orderInList's?
I think you can add code at the recursion terminate condition to check if the key is equal to Names Id or orderInList