Given the following object:
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
We're trying to find the path of myInventory, the issue is that the children's uuid will be different each time. Any idea how we can get the path to myInventory by providing it as a key and get the json path to it?
If things are dynamic, a programmatic key search could help
const ourObject = {
"payload": {
"streams": [
{
"children": {
"2165d20a-6276-468f-a02f-1abd65cad618": {
"additionalInformation": {
"narrative": {
"apple": "A",
"banana": "B"
},
"myInventory": {
"fruits": [
{
"name": "apple"
},
{
"name": "banana"
}
]
}
}
}
}
}
]
}
};
const getPath = (key, o) => {
if (!o || typeof o !== "object") {
return "";
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return key;
}
const path = getPath(key, o[keys[i]]);
if (path) {
return keys[i] + "." + path;
}
}
return "";
};
const getValueForKey = (key, o) => {
if (!o || typeof o !== "object") {
return undefined;
}
const keys = Object.keys(o);
for(let i = 0; i < keys.length; i++) {
if (keys[i] === key ) {
return o[key];
}
const value = getValueForKey(key, o[keys[i]]);
if (value) {
return value;
}
}
return undefined;
}
console.log(getPath("myInventory", ourObject))
console.log(getValueForKey("myInventory", ourObject))
Not sure if I understand the question right but
let uuid = '2165d20a-6276-468f-a02f-1abd65cad618';
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory
var changingKey = Object.keys(ourObject["payload"]["streams"][0]["children"])[0];
console.log(ourObject["payload"]["streams"][0]["children"][changingKey]["additionalInformation"]["myInventory"]);
Okay, you could create a helper function that gets the UUID. Since it's an object, the lookup is close to O(1) especially given the case that the children has only one key-value pair here.
function getUUIDFromPayload(payload) {
let obj = payload.streams[0].children
let uuid = Object.keys(obj)[0]
return uuid
}
Usage
const uuid = getUUIDFromPayload(payload)
ourObject.payload.streams[0].children[uuid].additionalInformation.myInventory
Related
First let me break down the data:
I have an array that contains 3 elements...
Each Element is an object with name and arrayOfJSON as keys...
Inside arrayOfJSON there could be any number of JSON strings as elements...
I need to capture the position where Alex#gmail occurs for both the array mess and arrayOfJSON
Result Should Be:
position_of_mess = [0,2]
position_of_arrayOfJSON_for_position_of_mess_0 = [0]
position_of_arrayOfJSON_for_position_of_mess_2 = [1]
What I'm trying at the moment:
For loop through mess, for loop through arrayOfJSON , and JSON.parse() for Alex#gmail.
going to take me a few mins to update.
If y'all think it can be done without a for-loop let me know.
Update: almost there
mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}
]
console.log(mess)
for (i = 0; i < mess.length; i++) {
console.log(JSON.parse(mess[i].arrayOfJSON))
for (m = 0; m < (JSON.parse(mess[i].arrayOfJSON)).length; m++) {
console.log("almost")
console.log((JSON.parse(mess[i].arrayOfJSON))[m])
}
}
mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}
]
console.log(mess)
holdMessPosition = []
for (i = 0; i < mess.length; i++) {
var pos = (JSON.parse(mess[i].arrayOfJSON)).map(function(e) {
return e.email;
})
.indexOf("Alex#gmail");
console.log("user position is " + pos);
if (pos !== -1) {
holdMessPosition.push(i)
}
}
console.log(holdMessPosition)
Parse your data
You want to be able to access keys inside the inner object "string"
Traverse your data
While visiting key-value pairs, build a scope thet you can later return
// Adapted from: https://gist.github.com/sphvn/dcdf9d683458f879f593
const traverse = function(o, fn, scope = []) {
for (let i in o) {
fn.apply(this, [i, o[i], scope]);
if (o[i] !== null && typeof o[i] === "object") {
traverse(o[i], fn, scope.concat(i));
}
}
}
const mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
}, {
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
}, {
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}];
// Parse...
mess.forEach(item => {
if (item.arrayOfJSON) {
item.arrayOfJSON = JSON.parse(item.arrayOfJSON);
}
});
traverse(mess, (key, value, scope) => {
if (value === 'Alex#gmail') {
console.log(
`Position: mess[${scope.concat(key).map(k => isNaN(k) ? `'${k}'` : k).join('][')}]`
);
}
});
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}
I have an Object:
{
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
I want to convert it to:
{
"Results": {
"circle": {
"circle": 0.06879016757011414
},
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": {
"square": 0.8266428709030151
}
}
}
Have tried this code:
var modData = {};
data = data.Results;
for (var key in data) {
if (data.hasOwnProperty(key)) {
modData[key] = data[key];
for (var innerKey in data[key]) {
modData[key] = data[key];
}
}
}
console.log("Modified is:", modData);
Unfortunately, this still returns the original object, what is it that I am doing which is wrong?
A jquery solution is fine as well.
Loop trough the properties with for .. in and any property is not an object replace it with one. Like this:
let x = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
for (key in x.Results) {
if (typeof x.Results[key] !== 'object')
x.Results[key] = {
[key]: x.Results[key]
}
}
console.log(x);
If you want to preserve the original object do this:
let data = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
}
data = data.Results;
modData = {};
for (key in data) {
if (typeof data[key] !== 'object')
modData[key] = { [key]: data[key] }
else
modData[key] = { [key]: data[key] }
}
console.log(modData);
You could check the type and if not an object then assign a new object with the same key and value.
This proposal uses computed property names for getting a variable as key for an object.
var object = { Results: { circle: 0.06879016757011414, quad: { exp: 0.8039023876190186, actual: 0.19609761238098145 }, square: 0.8266428709030151 } };
Object
.keys(object.Results)
.forEach(function (k) {
if (object.Results[k] && typeof object.Results[k] !== 'object') {
object.Results[k] = { [k]: object.Results[k] };
}
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The value that should be stored in modData should be the object itself rather than the value. This code gives the expected value
var modData = {};
data = data.Results;
for (var key in data) {
if (data.hasOwnProperty(key)) {
var temp = Object();
temp[key] = data[key];
modData[key] = temp;
for (var innerKey in data[key]) {
var temp = Object();
temp[key] = data[key];
modData[key] = temp;
}
}
}
const input = {
"Results": {
"circle": 0.06879016757011414,
"quad": {
"exp": 0.8039023876190186,
"actual": 0.19609761238098145
},
"square": 0.8266428709030151
}
};
const result = {
Results: {}
};
//If you want object construct specifically for "circle" & "square"
for (let key in input.Results) {
if (input.Results.hasOwnProperty(key)) {
if (key === 'circle') {
result.Results.circle = {
'circle': input.Results[key]
}
} else if (key === 'square') {
result.Results.square = {
'square': input.Results[key]
}
} else {
result.Results[key] = input.Results[key];
}
}
}
//Generically construct object if key is not object
for (let key in input.Results) {
if (input.Results.hasOwnProperty(key)) {
if (key !== 'object') {
result.Results[key] = {
[key]: input.Results[key]
}
}
}
}
console.log(result);
I have an array of objects which I am trying to loop over and check for a common key if it exists for all objects. if the specific key does not exist for all objects I return false.
Here is my code
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
var count = 0;
var out = false;
for (var i = 0; i < obj.length; i++) {
if (obj[i].hasOwnProperty('value')) {
count = i;
}
}
if (count == obj.length) {
out = true
}
}
console.log(test(x))
I am getting undefined. Cant figure out what am I missing here
A really simple way to do this is to use Array#every like this
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
return obj.every(a => a.hasOwnProperty("value"));
}
console.log(test(x))
Update
As rightfully mentioned by this comment first.
Here can be the simple solution for this object:
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}];
function test(obj) {
var keyCount = 0;
obj.forEach(function (item, index) {
item.hasOwnProperty('value') && ++keyCount;
});
return keyCount == obj.length;
}
console.log(test(x));
Here is my implementation, which finds every matching key, even nested keys, given a set of objects:
function recurse_obj(obj, cb, _stack = []) {
for (var k in obj) {
cb(k, obj[k], _stack);
if (obj.hasOwnProperty(k) && (obj[k] instanceof Object)) {
_stack.push(k);
recurse_obj(obj[k], cb, _stack);
_stack.pop();
}
}
}
function obj_all_keys(obj) {
var tmp = [];
recurse_obj(obj, (k, v, stack) => {
var ext = (stack.length) ? "." : "";
tmp.push(stack.join(".").concat(ext, k));
});
return tmp;
}
function key_intersection(...objs) {
var lookup = {};
objs.forEach(o => {
obj_all_keys(o).forEach(k => {
if (k in lookup === false)
lookup[k] = 0;
lookup[k]++;
});
});
for (var k in lookup)
if (lookup[k] !== objs.length)
delete lookup[k];
return lookup;
}
Here is the calling code:
var me = { name: { first: "rafael", last: "cepeda" }, age: 23, meta: { nested: { foo: { bar: "hi" } } } };
console.log(key_intersection(me, { name: { first: "hi" } }));
Output: { name: 2, 'name.first': 2 }
The object returned includes only the keys that are found in all the objects, the set intersection, the counts are from book-keeping, and not removed in the callee for performance reasons, callers can do that if need be.
Keys that are included in other nested keys could be excluded from the list, because their inclusion is implied, but I left them there for thoroughness.
Passing a collection (array of objects) is trivial:
key_intersection.apply(this, collection);
or the es6 syntax:
key_intersection(...collection);
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 a JSON data structure as shown below:
{
"name": "World",
"children": [
{ "name": "US",
"children": [
{ "name": "CA" },
{ "name": "NJ" }
]
},
{ "name": "INDIA",
"children": [
{ "name": "OR" },
{ "name": "TN" },
{ "name": "AP" }
]
}
]
};
I need to change the key names from "name" & "children" to say "key" & "value". Any suggestion on how to do that for each key name in this nested structure?
I don't know why you have a semicolon at the end of your JSON markup (assuming that's what you've represented in the question), but if that's removed, then you can use a reviver function to make modifications while parsing the data.
var parsed = JSON.parse(myJSONData, function(k, v) {
if (k === "name")
this.key = v;
else if (k === "children")
this.value = v;
else
return v;
});
DEMO: http://jsfiddle.net/BeSad/
Try this:
function convert(data){
return {
key: data.name,
value: data.children.map(convert);
};
}
Or if you need to support older browsers without map:
function convert(data){
var children = [];
for (var i = 0, len = data.children.length; i < len; i++){
children.push(convert(data.children[i]));
}
return {
key: data.name,
value: children
};
}
You could use a function like this :
function clonerename(source) {
if (Object.prototype.toString.call(source) === '[object Array]') {
var clone = [];
for (var i=0; i<source.length; i++) {
clone[i] = goclone(source[i]);
}
return clone;
} else if (typeof(source)=="object") {
var clone = {};
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
var newPropName = prop;
if (prop=='name') newPropName='key';
else if (prop=='children') newPropName='value';
clone[newPropName] = clonerename(source[prop]);
}
}
return clone;
} else {
return source;
}
}
var B = clonerename(A);
Note that what you have isn't a JSON data structure (this doesn't exist as JSON is a data-exchange format) but probably an object you got from a JSON string.