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
}
}
});
}
Related
I have an object that looks like the following:
const testObject = {
"NameA": {
"Name": {
"_text": "Peter"
}
},
"AgeA": {
"_comment": "line=2",
"age": {
"_text": "21"
}
},
"Birth": {
"_comment": "line=3",
"Birthday": {
"DateTimeSignUTCOffset": {
"Date": {
"_text": "191201"
},
"Time": {
"_text": "1123"
},
},
"Test": {
"Code": {
"_text": "1234"
}
},
}
}
}
I am trying to find any key with the key _text and get the corresponding value and the parent key.
i.e.
const result = {
"Name": "Peter",
"age": "21",
"Date": "191201",
"Time": "1123",
"Code": "1234"
};
I have tried the following by looping through the object but am unable to figure it out.
const result = {};
const find_items = (object) => {
console.log(Object.keys(object));
Object.keys(object).map((item) => {
console.log(object[item]);
if(object[item] !== '_text') {
find_items(object[item])
} else {
console.log(item)
}
});
};
find_items(testObject);
console.log(result);
Can someone could point me in the right direction?
You could take a recursive approach and check for object and if _text property exist take the value with the outer key or get the entries from the recursive call with the object.
At the end build an object from all entries.
const
flatEntries = object => Object
.entries(object)
.flatMap(([k, v]) => {
if (v && typeof v === 'object') return '_text' in v
? [[k, v._text]]
: flatEntries(v);
return [];
});
testObject = { NameA: { Name: { _text: "Peter" } }, AgeA: { _comment: "line=2", age: { _text: "21" } }, Birth: { _comment: "line=3", Birthday: { DateTimeSignUTCOffset: { Date: { _text: "191201" }, Time: { _text: "1123" } }, Test: { Code: { _text: "1234" } } } } },
result = Object.fromEntries(flatEntries(testObject));
console.log(result);
in English, what you want to do is:
create an empty object named "result", and then recursively iterate through the "object" object. each time you encounter a key linked to a sub-object which has a __text field, add that to the "result" object.
now just translate the above into JavaScript.
the keyword here is "recursively". your original code was not recursive.
your idea is pretty good, but you want to find _text keys anywhere nested inside the object. To find inner, nested, keys, you need to recurse your function if the value of some key happens to be an object.
result = {}
find_text_keys = (haystack, label) => {
Object.keys(ob).forEach(key => {
if (key === '_text') {
res[text] = ob["_text"];
} else if (typeof(ob[key]) === "object") {
find_text_keys(ob[key], key);
}
});
}
Then, calling the function with a default label f(object, "default_label") will populate the result dictionary as you desired.
I have a json request input below and would want to construct a specific json format that the backend needs using javascript. What is the best way or steps to construct them? Any help would be appreciated! Thanks.
Request input :
{
"Product": "abc"'
"Data": "{"Name":"John","Email":"john#example.com"}"
}
Request output to the backend as follow:
{
"variables": {
"Product": {
"value": "abc",
"type": "string"
},
"Data": {
"value": "{"Name":"John","Email":"john#example.com"}",
"type": "string"
}
},
"Key": "123"
}
Thanks in advance
You can just map over all the entries in your object.
Documentation: Object.entries() Array.reduce()
const input = {
Product: "abc",
Data: "{\"Name\":\"John\",\"Email\":\"john#example.com\"}"
};
const variables = Object.entries(input).reduce((output, [key, value]) => {
output[key] = {
type: typeof value,
value
};
return output;
}, {});
const result = {
variables,
key: '123'
};
console.log(result);
How do I check whether a value in an JSON key's value is an array if you don't know the key's name?
I may receive 2 different formats of a JSON object:
{
"person": [{
"id": "1",
"x": "abc",
"attributes": ["something"]
},
{
"id": "1",
"x": "abc"
}
]
}
Depending on the format I will parse it differently. My goal is to create an if statement that would detect whether the value of the key is an Array or just a value, without knowing the name of the key (in above code let's assume I don't really know the name of "attributes"). How do I achieve that? Not only do I have to loop through all person objects, but also all of it's keys.
I found a solution that does that knowing the name of the attribute and there's just one object "person", but don't know how to build on that with multiple "person" objects and not knowing the name of the key?
if (Array.isArray(json.person['attributes'])) // assuming I hold the JSON in json var and I parse it with JSON.parse
{
}
You can try something like this:
Data payload:
const payload = {
person: [
{
id: 1,
x: 'abc',
attributes: ['something']
},
{
id: 1,
x: 'abc'
}
]
};
Function that will return if some entry has an Array as value:
const arrayEntries = json => {
let response = [{
isArray: false,
jsonKey: null,
jsonValue: null
}];
Object.entries(json).map(entry => {
if (Array.isArray(entry[1])) {
response.push({
isArray: true,
jsonKey: entry[0],
jsonValue: entry[1]
});
}
});
return response;
}
Usage example:
payload.person.map(person => {
console.log(arrayEntries(person));
});
Return will be something like this:
Codepen link: https://codepen.io/WIS-Graphics/pen/ExjVPEz
ES5 Version:
function arrayEntries(json) {
var response = [{
isArray: false,
jsonKey: null,
jsonValue: null
}];
Object.entries(json).map(function(entry) {
if (Array.isArray(entry[1])) {
response.push({
isArray: true,
jsonKey: entry[0],
jsonValue: entry[1]
});
}
});
return response;
}
payload.person.map(function(person) {
console.log(arrayEntries(person));
});
This question already has answers here:
Filtering object properties based on value
(8 answers)
Closed 3 years ago.
Say I have an object that looks like this:
{
"data": {
"postsConnection": {
"groupBy": {
"author": [
{
"key": "xyz",
"connection": {
"aggregate": {
"count": 5
}
}
},
{
"key": "abc",
"connection": {
"aggregate": {
"count": 3
}
}
}
]
}
}
}
}
How would one access the value of count corresponding to the author element that has, say, xyz as its key? I know for this particular example I could just do this:
const n = data.postsConnection.groupBy.author[0].connection.aggregate.count
But that would mean knowing in advance which element in the array holds the desired value for key, which isn't the case in my context.
If the author can appear multiple times, you can .filter() the array stored at author and then .map() the results to the count:
const data = {data:{postsConnection:{groupBy:{author:[{key:"xyz",connection:{aggregate:{count:5}}},{key:"abc",connection:{aggregate:{count:3}}}]}}}};
const author = "xyz";
const res = data.data.postsConnection.groupBy.author.filter(({key}) => key === author).map(obj => obj.connection.aggregate.count);
console.log(res);
// If you want to get the total of all counts for the given author, you can use reduce on the result to sum:
const totalCountsForAuthor = res.reduce((acc, n) => acc+n, 0);
console.log(totalCountsForAuthor);
If the author can only appear once, you can use .find() instead of .filter() like so:
const data = {data:{postsConnection:{groupBy:{author:[{key:"xyz",connection:{aggregate:{count:5}}},{key:"abc",connection:{aggregate:{count:3}}}]}}}};
const author = "xyz";
const res = data.data.postsConnection.groupBy.author.find(({key}) => key === author).connection.aggregate.count
console.log(res);
You can use Array#find to get the first instance inside an array that meets a certain condition (in your case, the first instance whose key value is equal to the key value you want).
var obj = {"data":{"postsConnection":{"groupBy":{"author":[{"key":"xyz","connection":{"aggregate":{"count":5}}},{"key":"abc","connection":{"aggregate":{"count":3}}}]}}}};
function getAuthorByKey(key) {
return obj.data.postsConnection.groupBy.author.find(author => author.key === key);
}
console.log(getAuthorByKey("xyz").connection.aggregate.count);
console.log(getAuthorByKey("abc").connection.aggregate.count);
If the author array always exists:
const data = {
postsConnection: {
groupBy: {
author: [{
key: "xyz",
connection: {
aggregate: {
count: 5
}
}
}, {
key: "abc",
connection: {
aggregate: {
count: 3
}
}
}]
}
}
};
function getCount(keyVal) {
const element = data.postsConnection.groupBy.author.find(item => item.key === keyVal)
return element.connection.aggregate.count || "";
}
console.log(getCount('xyz'))
var data = { "data": {
"postsConnection": {
"groupBy": {
"author": [
{
"key": "xyz",
"connection": {
"aggregate": {
"count": 5
}
}
},
{
"key": "abc",
"connection": {
"aggregate": {
"count": 3
}
}
}
]
}
}
}
};
data.data.postsConnection.groupBy.author.forEach((autor) => {
if(autor.key === "xyz")
console.log(autor.connection.aggregate);
});
You can make use of array find, to find the author by "key".
Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
const author = data.postsConnection.groupBy.author.find((author) => author.key === "xyz")
CodePen:
https://codepen.io/gmaslic/pen/wvwbLoL
Then you can access all the properties from found "author"
Using $.getJSON to get data from external .json file with following content.
{
data:[
{
"1apps":"1",
"abc" "xyz"
},
{
"apps":"2",
"abc" "xyz"
},
{
"2apps":"3",
"abc" "xyz"
}
]
}
I want to find the data which keys matching apps. In this case, 1apps, apps, 2apps will be the output.
You can use filter and then iterate on obj , then use a include function determines whether a string contains the characters of a specified string
var obj = {
data: [{
"1apps": "1",
"abc": "xyz"
},
{
"apps": "2",
"abc": "xyz"
},
{
"2apps": "3",
"abc": "xyz"
}
]
};
var list = obj["data"];
var matchedKeys = [];
list.filter(function(k, v) {
for (var i in k) {
if (i.includes('apps')) {
matchedKeys.push(i);
return k;
}
}
});
console.log(list)
console.log(matchedKeys);
You can simply use reduce and filter to get the keys that include apps
const obj = {
data:[
{
"1apps":"1",
"abc" :"xyz"
},
{
"apps":"2",
"abc" :"xyz"
},
{
"2apps":"3",
"abc" :"xyz"
}
]
}
const res = obj.data.reduce((a,b) => a.concat(...Object.keys(b).filter(x => /apps/.test(x))), []);
console.log(res);