consider this example
let obj = {
"minute": {
"data": [
{
"s": [0],"values": {
"TV Web": {
"P": [0],
"S": [0]
}
}
},
{ },
],
"product": ["Tom"]
},
"ads": { },
}
for(let entry in obj){
console.log(obj[entry].product[0])
}
if you run the snippet it shows "TOM" and undefined.
How can I select only Tom? without having undefined?
you can just directly access to that path obj["minute"].product[0];
if you want check in all of property, then you can skip undefined value
for(let entry in obj){
if (obj[entry].product){
console.log(obj[entry].product[0]);
}
// or use ternari
obj[entry].product && console.log(obj[entry].product[0]);
// or use library like `lodash`
console.log(lodash.get(obj[entry], "product[0]"));
}
Related
I have a question about how to loop an object in typescript and to get the value that I want.
my object looks like this:
mockdata = {
"subobj1": {
"order": 1
"value": "abc"
},
"subobj2": {
"order": 2
"value": "aaa"
},
...
}
I want to loop this object and only get the subobject, if order == 1
what I expect is to get object
"subobj1": {
"order": 1
"value": "abc"
}
any solutions?
Just loop through the object using for in syntax and find the respective value!
const mockdata = {
"subobj1": {
"order": 1,
"value": "abc"
},
"subobj2": {
"order": 2,
"value": "aaa"
},
}
let output;
for (const property in mockdata) {
if (mockdata[property].order === 1) {
output = {
[property]: mockdata[property]
}
break;
}
}
console.log('result', output);
Here's a pretty slim way to do it. I usually use Object.keys or .entries to all my obj for loops
const arrOfOrderEqualToOne = Object.entries(mockdata).filter(([key, value]) => value.order === 1));
Try this
let mockdata = {
"subobj1": {
"order": 1,
"value": "abc"
},
"subobj2": {
"order": 2,
"value": "aaa"
},
}
let temp;
Object.keys(mockdata).forEach(key=>{
if(mockdata[key].order==1){
temp=mockdata[key]
}
})
console.log(temp)
I feel like this is mostly an issue with how I'm looping through the JSON, so am posting that first. This is a series of JSON responses from Promise.allSettled() posted below.
The problem I am having is with the second "status" object between content and anoObject1 as I'm looping through the JSON responses. I've shown some console.logs() below that are successful
Here is the series of JSON responses:
[
{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject2": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
Here are the async fetch calls:
export async function allCallouts(key, value){
const BASE_URL = 'https://baseurl.com/service/'
const API_KEY = 'apikey'
const endpoint1 = 'https://url1.com/a/';
const endpoint2 = 'https://url1.com/b/';
try{
const results = await Promise.allSettled(
[
fetch(endpoint1).then((response) => response.json()),
fetch(endpoint2).then((response) => response.json()),
]
)
return results
} catch (error){
console.log(error)
}
}
Here is the function I am calling the first function from
async handleFetchCallouts() {
returnedResults;
await allCallouts(key, value)
.then(results => {
this.returnedResults = results
}).catch(err => {
console.log('this is err: ' + err);
})
let arrayLength = this.returnedResults.length
for (var i = 0; i < arrayLength; i++) {
//I am able to console.log(this.returnedResults[i].value.content)
//it returns the response and number I am expecting
//but the structure of the JSON response (above) is tripping me up
if (this.returnedResults[i].value.content['object1'] != null) {
//I can console.log() this successfully
console.log(this.returnedResults[i].value.content['object1'].kv)
}
if (this.returnedResults[i].value.content['anoObject1'] != null) {
//having trouble getting to this object and looping through each
}
}
}
Thank you for any help! If you see other design flaws with my code or an easier way to do things, please suggest.
Create a recursive function and dont use any hardcoded key. Iterate through the content and check if value is an array using Array.isArray. If so then handle it in a different function and so for if value is of type object
const arrayLength = [{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject1": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
for (let i = 0; i < arrayLength.length; i++) {
const content = arrayLength[i].value.content;
// checking if value is of type array or object
if (Array.isArray(content)) {
handleContentArray(content)
} else if (content && typeof(content) === 'object') {
handleContentObject(content)
}
}
function handleContentArray(contentArray) {
// iterate the array
contentArray.forEach(item => {
// if the content of the array is an object then call the function which handles the object
if (item && typeof item === 'object') {
handleContentObject(item)
}
})
}
function handleContentObject(contentObject) {
// iterate through the key
for (let keys in contentObject) {
// if the value of the key is an object then recursively call the same function
if (contentObject && typeof(contentObject[keys]) === 'object') {
return handleContentObject(contentObject[keys])
} else {
// log the key value pair
console.log(`KEY:- ${keys}, VALUE: - ${contentObject[keys]}`)
}
}
}
You can use Array.isArray() to ascertain if an object is an Array and customize how you handle the object accordingly.
// Same structure as in the question, but removed extraneous
// fields and compacted for the sake of brevity.
const input = `[
{"value":{"content":{"object1":{"kv":"Y"}}}},
{"value":{"content":[
{"anoObject1":{"ano":"A"}},
{"anoObject1":{"ano":"B"}}
]}}]`;
const result = JSON.parse(input);
for (const r of result) {
const content = r.value.content;
if (Array.isArray(content)) {
for (const c of content) {
console.log(`anoObject1.ano = ${c.anoObject1.ano}`);
}
} else {
console.log(`object1.kv = ${content.object1.kv}`);
}
}
For your second if statement in the for loop, you would have to iterate through all items under value.content. Replace the second if statement with this for a plug and play:
if (Array.isArray(this.returnedResults[i].value.content)) for (let i of this.returnedResults[i].value.content) {
}
Inside the new loop, i will be equivalent to
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
The reason for this is that the second if statement was attempting to find a property/key of an array instead of each object in the array of objects.
I would also recommend reading up on the following to make your coding easier/better:
let
for...in/for...of
truthy/falsy
I am obtaining a JSON from another application. I would like to parse that JSON and read the data present in them. The JSON contains some of the user-defined data which are dynamic and the key/value pair can be dynamic so I am a bit confused about how to read these dynamic data and do further processing.
Following is the sample JSON that I would like to process:
{
"context": [
{
"one": "https://example.one.com"
},
{
"two": "https://example.two.com"
},
{
"three": "https://example.three.com"
}
],
"name": "Batman",
"age": "30",
"one:myField": {
"two:myField2": "Hello"
},
"three:myField3": "Hello2"
}
I am able to read some of the static/well-defined data directly such as name & age but I am not understanding how to read some of the user-defined/dynamic data from this JSON as it does not have a definite key/value or there is no guarantee that it will appear in the order after the age property.
I am trying to find a way to read/obtain all the user-defined data from this JSON:
"one:myField": {
"two:myField2": "Hello"
},
"three:myField3": "Hello2"
Is there a direct way to achieve this or use some library? I am developing the application using Vuejs/Nuxtjs.
I think that's not the best api you are using, you should have constant object parameters that you always know how to find things. If you want to find not known parameters you can parse JSON to object and loop throug it.
const object = { a: 1, b: 2, c: 3 };
for (const property in object) {
console.log(`${property}: ${object[property]}`);
}
You can simply achieve that by iterating over Object.keys().
Demo :
const jsonData = {
"context": [
{
"one": "https://example.one.com"
},
{
"two": "https://example.two.com"
},
{
"three": "https://example.three.com"
}
],
"name": "Batman",
"age": "30",
"one:myField": {
"two:myField2": "Hello"
},
"three:myField3": "Hello2"
};
Object.keys(jsonData).forEach(key => {
if (typeof jsonData[key] === 'object') {
Object.keys(jsonData[key]).forEach(innerObjKey => {
console.log(innerObjKey, jsonData[key][innerObjKey])
})
} else {
console.log(key, jsonData[key])
}
})
Combining Object.keys with a recursive function, even if you have multiple nested objects, it will work without having to refactor your code everytime!
const jsonData = {
context: [
{
one: "https://example.one.com",
},
{
two: "https://example.two.com",
},
{
three: "https://example.three.com",
},
],
name: "Batman",
age: "30",
"one:myField": {
"two:myField2": "Hello",
"one_nested:myField": {
another_nested_key: "another_nested_value",
},
},
"three:myField3": "Hello2",
};
recursive(jsonData);
function recursive(nestedKey) {
if (typeof nestedKey !== "object") return;
Object.keys(nestedKey).forEach((key) => {
if (typeof nestedKey[key] === "object") {
recursive(nestedKey[key]);
} else {
console.log(key, nestedKey[key]);
// add your conditions here
if (key === "name") {
// bla bla bla
}
}
});
}
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 have some JSON like this:
{
"a": { "text": "text", "index": 5 },
"b": { "text": "text", "index": 3 },
"c": { "text": "text", "index": 1 },
}
Now I need to interate this object and call a function on every property of the first level (a, b and c), but I have to do it on order using the "index" property, like "c" first, then "b" and last "a".
However I read that I shouldn't use a for in loop:
A for...in loop iterates over the properties of an object in an arbitrary order (see the delete operator for more on why one cannot depend on the seeming orderliness of iteration, at least in a cross-browser setting).
then how I can do this?
Thanks
You could,
Get the properties of the object as an array using Object.keys().
Sort the properties of the object using sort().
Use forEach() to iterate through the sorted items (which is executed in ascending order of the array).
var items = {
"a": {
"text": "text",
"index": 5
},
"b": {
"text": "text",
"index": 3
},
"c": {
"text": "text",
"index": 1,
}
};
Object.keys(items).sort(function(a, b) {
return items[a].index - items[b].index;
}).forEach(doStuff);
function doStuff(key) {
console.log(items[key]);
}
You can use getOwnPropertyNames
let obj = {
"a": { "text": "text", "index": 5 },
"b": { "text": "text", "index": 3 },
"c": { "text": "text", "index": 1 }
};
function test(p) {
console.log(p);
}
Object.getOwnPropertyNames(obj)
.reverse()
.forEach(function(p){
test(obj[p]);
});
You can try the following:
Covert the object to an array with elements in sorted order based on the index.
Than simply forEach() on the sorted properties.
Sort function can be implemented as :
var obj = {
"a": { "text": "text", "index": 5 },
"b": { "text": "text", "index": 3 },
"c": { "text": "text", "index": 1},
}
function sortProperties(obj, sortedBy, isNumericSort, reverse) {
sortedBy = sortedBy || 1; // by default first key
isNumericSort = isNumericSort || false; // by default text sort
reverse = reverse || false; // by default no reverse
var reversed = (reverse) ? -1 : 1;
var sortable = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
sortable.push([key, obj[key]]);
}
}
if (isNumericSort)
sortable.sort(function (a, b) {
return reversed * (a[1][sortedBy] - b[1][sortedBy]);
});
else
sortable.sort(function (a, b) {
var x = a[1][sortedBy].toLowerCase(),
y = b[1][sortedBy].toLowerCase();
return x < y ? reversed * -1 : x > y ? reversed : 0;
});
return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ]
}
sortProperties(obj, 'index', true, false);
The another solution is store the object keys and reverse it, then iterate with the object keys.
var obj = {
"a": { "text": "text", "index": 5 },
"b": { "text": "text", "index": 3 },
"c": { "text": "text", "index": 1 }
};
var yourFunction = console.log;
var keys = Object.keys(obj);
keys.reverse();
for (var i = 0; i < keys.length; i++) {
yourFunction(obj[keys[i]]);
}
you can also make use of reverse() method of javascript if you want to access the json items in reverse order.
get the array of all the keys of json using Object.keys()
reverse the array using reverse() method
and finally you can make use of javascript forEach() method to work on the items of the json. Sample code is shown below
let obj = {
"a": { "text": "text", "index": 5 },
"b": { "text": "text", "index": 3 },
"c": { "text": "text", "index": 1 },
}
Object.keys(obj)
.reverse()
.forEach(ele => {
console.log(obj[ele]);
});
visit This link to know more about reverse() method
Probably you should use Object.keys to get a list of all the properties, sort that list, then iterate over it.