Access a object value within another object - javascript

I currently have a Object which looks like so:
{
"Best Fare Description": {
"text": {
"value": "One",
"type": "TEXT"
}
},
"Brand ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Max Elapse Time": {
"integer": {
"value": 4,
"type": "INTEGER"
}
},
"Max Number of Connections": {
"integer": {
"value": 5,
"type": "INTEGER"
}
}
}
I am trying to iterate through the object and create an array of only the values. So for this object I would return an array of
["One","test","test",4,5]
What I've Tried:
data being the object
const tempList = [];
for (var key in data) {
for (var key2 in data[key]) {
for (var key3 in data[key][key2]) {
tempList.push(key3['value'])
}
}
}
However it seems like I am not doing something correct, as I get undefined or errors when I push into the array. Is there an easier/More Efficient way to accomplish this? Any help would be appreciated!

Because of the dynamic keys, you could take the values and map the last item.
var data = { "Best Fare Description": { text: { value: "One", type: "TEXT" } }, "Brand ID": { text: { value: "test", type: "TEXT" } }, "Program ID": { text: { value: "test", type: "TEXT" } }, "Max Elapse Time": { integer: { value: 4, type: "INTEGER" } }, "Max Number of Connections": { integer: { value: 5, type: "INTEGER" } } },
result = Object.values(data).map(o => Object.values(o)[0].value);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

The easiest thing is to loop over the Object.values of the two levels using map and reduce to build your array:
let obj = {"Best Fare Description": {"text": {"value": "One","type": "TEXT"}},"Brand ID": {"text": {"value": "test","type": "TEXT"}},"Program ID": {"text": {"value": "test","type": "TEXT"}},"Max Elapse Time": {"integer": {"value": 4,"type": "INTEGER"}},"Max Number of Connections": {"integer": {"value": 5,"type": "INTEGER"}}}
let arr = Object.values(obj).reduce((arr, item) => {
arr.push(...Object.values(item).map(inner => inner.value))
return arr
}, [])
console.log(arr)
Newer javascript engines will let you simplify a bit with flatMap:
let obj = {"Best Fare Description": {"text": {"value": "One","type": "TEXT"}},"Brand ID": {"text": {"value": "test","type": "TEXT"}},"Program ID": {"text": {"value": "test","type": "TEXT"}},"Max Elapse Time": {"integer": {"value": 4,"type": "INTEGER"}},"Max Number of Connections": {"integer": {"value": 5,"type": "INTEGER"}}}
let arr = Object.values(obj).flatMap(item => Object.values(item).map(inner => inner.value))
console.log(arr)

It seems you innermost object's structure stays the same. In that case, you could slightly change your existing code to do something like the following:
const tempList = [];
for (let key in data) {
for (let key2 in data[key]) {
tempList.push(data[key][key2].value);
}
}

Here's a recursive function that will do what you need (it will work with any shape of object):
const findValues => obj => Object.keys(obj).reduce((acc,key)=>{
if(key==='value'){
acc.push(obj[key])
}else if(typeof obj[key]==='object'){
acc.push(findValues(obj[key]))
}
return acc.flat()
},[])
So if your object is:
const obj = {
"Best Fare Description": {
"text": {
"value": "One",
"type": "TEXT"
}
},
"Brand ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Max Elapse Time": {
"integer": {
"value": 4,
"type": "INTEGER"
}
},
"Max Number of Connections": {
"integer": {
"value": 5,
"type": "INTEGER"
}
}
}
You would call it like this:
findValues(obj) // ["One", "test", "test", 4, 5]
A more generic version:
const findValues = selector => obj => Object.keys(obj).reduce((acc,key)=>{
debugger
if(key===selector){
acc.push(obj[key])
}else if(typeof obj[key]==='object'){
acc.push(findValues(selector)(obj[key]))
}
return acc.flat()
},[])
findValues('value')(obj) // ["One", "test", "test", 4, 5]
Codepen here: https://codepen.io/jenko3000/pen/yWWJxg

You're saying tempList.push(key3['value']), but key3 is a string, not an array. You also don't need 3 loops, you only need 2.
let data = {
"Best Fare Description": {
"text": {
"value": "One",
"type": "TEXT"
}
},
"Brand ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "TEXT"
}
},
"Max Elapse Time": {
"integer": {
"value": 4,
"type": "INTEGER"
}
},
"Max Number of Connections": {
"integer": {
"value": 5,
"type": "INTEGER"
}
}
}
const tempList = [];
for (var key in data) {
for (var key2 in data[key]) {
if (data[key][key2]['value'])
tempList.push(data[key][key2]['value'])
}
}
console.log(tempList);

Related

JavaScript / typescript: unable to regenerate object

I have an object as specified below:
{
"player settings": [
{
"id": 1,
"labelName": "site language",
"labelValue": [
{
"id": 1,
"languageName": "ARABIC",
"language": "لغتك",
"languageCode": "AE"
},
{
"id": 2,
"languageName": "CHINESE",
"language": "你的语言",
"languageCode": "ZH"
},
],
"dataType": "DD",
"selectedData": "2"
},
{
"id": 2,
"labelName": "subtitle language",
"labelValue": [
{
"id": 1,
"languageName": "ARABIC",
"language": "لغتك",
"languageCode": "AE"
},
{
"id": 2,
"languageName": "CHINESE",
"language": "你的语言",
"languageCode": "ZH"
},
],
"dataType": "DD",
"selectedData": "1"
},
]
},
{
"channel": [
{
"id": 11,
"labelName": "channel label",
"dataType": "TX",
"selectedData": "jhfh"
}
]
},
{
"others": [
{
"id": 16,
"labelName": "others label",
"dataType": "TX",
"selectedData": "dhgdhg"
}
]
}
How can I modify and re-generate the object with the following conditions:
if dataType === 'DD' then convert selectedData into number.
I wrote the below code but stuck here:
for (var j = 0; j < this.myobject.length; j++){
this.myobject.forEach(obj => {
console.log(obj)
});
}
You can use for..in
let data = {"player settings": [{"id": 1,"labelName": "site language","labelValue": [{"id": 1,"languageName": "ARABIC","language": "لغتك","languageCode": "AE"},{"id": 2,"languageName": "CHINESE","language": "你的语言","languageCode":"ZH"},],"dataType": "DD","selectedData": "2"},],"player settings2": [{"id": 1,"labelName": "site language","labelValue": [{"id": 1,"languageName": "ARABIC","language": "لغتك","languageCode": "AE"},{"id": 2,"languageName": "CHINESE","language": "你的语言","languageCode":"ZH"},],"dataType": "NO DD","selectedData": "2"},]}
for (let key in data) {
data[key].forEach(obj => {
if (obj.dataType === "DD") {
obj.selectedData = +(obj.selectedData || 0)
}
})
}
console.log(data)
Immutable approach
let data = {"player settings": [{"id": 1,"labelName": "site language","labelValue": [{"id": 1,"languageName": "ARABIC","language": "لغتك","languageCode": "AE"},{"id": 2,"languageName": "CHINESE","language": "你的语言","languageCode":"ZH"},],"dataType": "DD","selectedData": "2"},],"player settings2": [{"id": 1,"labelName": "site language","labelValue": [{"id": 1,"languageName": "ARABIC","language": "لغتك","languageCode": "AE"},{"id": 2,"languageName": "CHINESE","language": "你的语言","languageCode":"ZH"},],"dataType": "NO DD","selectedData": "2"},]}
let newObj = {}
for (let key in data) {
newObj[key] = data[key]
data[key].forEach(obj => {
if (obj.dataType === "DD") {
newObj.selectedData = +(obj.selectedData || 0)
}
})
}
console.log(newObj)
We can use filter on the main obj and then proceed modifying the object.
function modifyDataToNumber(){
let myObject = jsonObj['player settings'];
let ddMyObject = myObject.filter((row)=>(row["dataType"]==="DD"));
console.log(ddMyObject[0]["selectedData"]);
ddMyObject.forEach((row,index)=>{
ddMyObject[index]["selectedData"] = +ddMyObject[index]["selectedData"];
})
console.log(jsonObj);
}
modifyDataToNumber();
I would do something like this
const json = {
"player settings": [
{
"id": 1,
"labelName": "site language",
"labelValue": [
{
"id": 1,
"languageName": "ARABIC",
"language": "لغتك",
"languageCode": "AE"
},
{
"id": 2,
"languageName": "CHINESE",
"language": "你的语言",
"languageCode": "ZH"
},
],
"dataType": "DD",
"selectedData": "2"
},
]
};
json['player settings'] = json['player settings'].map(setting => {
if (setting.dataType === 'DD') {
const updatedSetting = {
...setting,
selectedData: parseInt(setting.selectedData)
};
return updatedSetting;
}
return setting;
});
console.log('Result', json);
Since you say "re-generate", I assume you want an immutable approach to this (that is, generate a copy of the data with the desired changes, rather than changing the original object).
To that, you can use spread syntax and Array#map:
let convertSetting = setting => ({
...setting,
selectedData: setting.dataType === "DD"
? parseInt(setting.selectedData)
: setting.selectedData
});
let convert = x => ({
...x,
["player settings"]: x["player settings"].map(convertSetting)
});
Then you can use that function as convert(yourOriginalObject).

Nested json object into single json objects with repeating parent details to construct html table

This is a nested json file and I am trying to arrange it in a readable format to display in a table
I tried to manually put all the keys and values with in a for loop but there should be an elegant way to achieve this and hence I am reaching SO.
The actual JSON is quite a nested one and needed time to execute data with 500k rows
The result should be enhanced JSON with parent values appearing for child values as well
var property = {
"data": [{
"ID": "123456",
"name": "Coleridge st",
"criteria": [
{
"type": "type1",
"name": "name1",
"value": "7",
"properties": []
},
{
"type": "type2",
"name": "name2",
"value": "6",
"properties": [
{
"type": "MAX",
"name": "one",
"value": "100"
}, {
"type": "MIN",
"name": "five",
"value": "5"
}
]
},
{
"type": "type3",
"name": "name3",
"value": "5",
"properties": [{
"type": "MAX1",
"name": "one6",
"value": "1006"
}, {
"type": "MIN2",
"name": "five6",
"value": "56"
}]
}
]
},
{
"ID": "456789",
"name": "New Jersy",
"criteria": [
{
"type": "type4",
"name": "name4",
"value": "6",
"properties": [{
"type": "MAX12",
"name": "one12",
"value": "10012"
}, {
"type": "MIN23",
"name": "five12",
"value": "532"
}]
}
]
}]
};
var output = [];
property.data.forEach(function (users) {
var multirows = {
id: users.ID,
name: users.name,
};
for (var i = 0; i < users.criteria.length; i++) {
var criterias = {
type: users.criteria[i].type,
name: users.criteria[i].name,
value: users.criteria[i].value,
}
var mat_contacts_rows;
if (!isEmpty(users.criteria[i].properties)) {
for (var j = 0; j < users.criteria[i].properties.length; j++) {
var property = {
type: users.criteria[i].properties[j].type,
name: users.criteria[i].properties[j].name,
value: users.criteria[i].properties[j].value
};
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
} else {
var property = [];
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
}
});
console.log(JSON.stringify(output, undefined, 2))
function isEmpty(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key))
return false;
}
return true;
}
I think this could be a great exercise to you to don't answer your question but to give you some tips. You should first look at : Lodash wish has a bunch of usefull method to help you doing what you'r trying to do.
In a second time you should avoir using .forEach or for loops and try using Array.prototype.map or Array.prototype.reduce

Reformatting JSON by Placing Object into Array

I'm trying to reformat my JSON to work with an external API
My current JSON Structure:
{
"serviceConfigs": {
"servicecode": "SC1",
"specifiers": {
"Brand ID": {
"text": {
"value": "test",
"type": "text"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "text"
}
}
}
}
}
Desired Output:
{
"serviceConfigs": [{
"servicecode": "SC1",
"specifiers": {
"Brand ID": {
"text": {
"value": "test",
"type": "text"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "text"
}
}
}
}]
}
So currently serviceConfigs is in an Object, but I want it into an array
My current thought process is to use a push command, but I'm not sure how to access the object (Loop?).
You can access the key's value and place it back to same key in desired format.
let obj = {"serviceConfigs": {"servicecode": "SC1","specifiers": {"Brand ID": {"text": {"value": "test","type": "text"}},"Program ID": {"text": {"value": "test","type": "text"}}}}}
obj.serviceConfigs = [obj.serviceConfigs]
console.log(obj)

obj[i] is not iterable in javascript while transforming data

I am trying to transform my data from one format to another format , but I am getting error obj[i] is not iterable why I want to get expected output as shown below in variable
const data = {
"GENERAL": {
"value": null,
"type": "LABEL",
},
"Mobile NUMBER": {
"value": "04061511",
"type": "FIELD",
},
"Abc NUMBER": {
"value": "89999",
"type": "FIELD",
},
"Personal Info": {
"value": null,
"type": "LABEL",
},
"Address": {
"value": "g-78",
"type": "FIELD",
}, "local": {
"value": "090099",
"type": "FIELD",
}
}
const obj = {}
for (var i in data) {
const {type} = data[i];
if (type === 'LABEL') {
obj[i] = []
} else {
obj[i] = [...obj[i], data[i]]
}
}
console.log(obj)
const expectedout = {
"GENERAL": [{
"value": "04061511",
"type": "FIELD",
"displaytext": "Mobile NUMBER"
}, {
"value": "89999",
"type": "FIELD",
"displaytext": "Abc NUMBER"
}],
"Personal Info": [{
"value": "g-78",
"type": "FIELD",
"displaytext": "Address"
}, {
"value": "090099",
"type": "FIELD",
"displaytext": "local"
}]
}
Is there any better approach to transform my current data to expected data?I am ES6 in react
here is my code
https://jsbin.com/sesipuzeni/1/edit?html,js,console,output
Update
var obj = {
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second"
};
for (var i in obj) { console.log(i); };
VM5628:8
it seems object property don't have guarantee.yes is correct when you have number and string
but when you have always "string" it comes in same order
var obj = {
"first":{a:"jjj"},
"yyy":{a:"jjqej"},
"ttt":{a:"jjsqj"},
"ggg":{a:"jjjs"},
"second":{a:"jjcj"}
};
for (var i in obj) { console.log(i); };
The problem is that when you're processing the next element of the original object, i is no longer the key of the element containing the array of values. You need to save that in another variable.
const data = {
"GENERAL": {
"value": null,
"type": "LABEL",
},
"Mobile NUMBER": {
"value": "04061511",
"type": "FIELD",
},
"Abc NUMBER": {
"value": "89999",
"type": "FIELD",
},
"Personal Info": {
"value": null,
"type": "LABEL",
},
"Address": {
"value": "g-78",
"type": "FIELD",
},
"local": {
"value": "090099",
"type": "FIELD",
}
}
const obj = {};
var lastLabel;
for (var i in data) {
if (data[i].type === 'LABEL') {
obj[i] = []
lastLabel = i;
} else {
data[i].displaytext = i;
obj[lastLabel] = [...obj[lastLabel], data[i]]
}
}
console.log(obj)
Note that this whole approach depends on object properties retaining their order, which isn't guaranteed in JavaScript. But it happens to work in most existing implementations, I think.

Search a Javascript Object for the position of a specific ID? [duplicate]

This question already has answers here:
Find by key deep in a nested array
(21 answers)
Closed 4 years ago.
I have a Javascript object with lots of different sections. How can I search through all of the sections to find the position of a specific ID? The ID's that I am searching for are not in a specific location, and can be located in any of the tree branches.
For example, I am searching for this ID:
xobmnbjxg0g_1527269346261
And I am trying to output the position of that ID, which would be this:
app['structure'][0]['if-children'][0]['id']
My Javascript Object:
var app = {
"structure": [
{
"id": "0",
"type":"IF",
"parameters": [
{
"id": "xobmnbjxg0g_1527269346260",
"type": "field",
"value": "CV_TEST_SPOT1X"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346261",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
],
"else-children":[
]
}
],
"else-children":[
{
"id": "xobmnbjxg0g_1527269346262",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_152726934626X"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_152726934626Y"
}
]
}
]
},
{
"id": "xobmnbjxg0g_1527269346263",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346264",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children":[
{
"id": "xobmnbjxg0g_1527269346265",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_1527269346266"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346267"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346268"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346269"
}
]
}
]
};
Interesting puzzle/question.
pretty sure there are some edge cases im missing but this seems to pass some tests.
function is(obj, type){
return Object.prototype.toString.call(obj) === `[object ${type}]`;
}
function findPosition(obj, mykey, myval, res){
if(is(obj, "Object")){
if(mykey in obj && obj[mykey] === myval){
res.tree.push(mykey);
res.found = true;
} else {
for( let key in obj){
if(res.found) break;
res.tree.push(key);
findPosition(obj[key], mykey, myval, res);
}
if(!res.found) res.tree.pop();
}
} else if(is(obj, "Array")){
for(let i = 0; i < obj.length; i++){
if(res.found) break;
res.tree.push(i);
findPosition(obj[i], mykey, myval, res);
}
if(!res.found) res.tree.pop();
} else {
res.tree.pop();
}
return res;
}
Usage and output
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "mys", {tree:[], found: false})
> tree: Array(0), found: false}
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "my", {tree:[], found: false})
> {found: true, tree: [0, "one", "two", 0, "id", 0, "id"]}
For finding if current obj you are iterating over is an Array you can also use Array.isArray

Categories

Resources