How to dynamically build a data structure in pure JavaScript? - javascript

Is there any plugin that allow to dynamically build following data structure in plain JavaScript object or JSON?
This is the structure I would like to implement:
Check my plunker (https://plnkr.co/edit/1eWjXLPumuOMhv8BjaNw?p=preview)
{
"name": "Select0",
"id": "select0",
"values": [
"Option1",
"Option2"
],
"dependent": {
"name": "Select1",
"id": "select1",
"values": {
"Option1": [
"Option11",
"Option12"
],
"Option2": [
"Option21",
"Option22"
]
},
"dependent": {
"name": "Select2",
"id": "select2",
"values": {
"Option1": {
"Option11": [
"Option111",
"Option112"
],
"Option12": [
"Option121",
"Option122"
]
},
"Option2": {
"Option21": [
"Option211",
"Option212"
],
"Option22": [
"Option221",
"Option222"
]
}
},
"dependent": []
}
}
}

Note that you can set values on properties on an object and then print it as a JSON.
var obj = {};
object.name = "Select0";
// Set more properities.
// Stringify object to JSON format looking as the one in the question.
var json = JSON.stringify(obj, null, 2);
// Verify by printing on the screen.
console.log(json);

Related

Transforming a complex object into an array

I am creating a React app using data from an API. the response data is a long complicated object that looks something like this:
{
"Frozen Products": [
{
"_id": "6181849285e8d8f86be2d9df",
"name": "Peas (800g)",
"category_id": "6181841060c425f76e57b603",
"slug": "vegetables",
"quantity": 16,
"price": {
"amount": 3.00
},
"thumbnail":"URI ...",,
"images": [
"URI ...",
],
"synonyms": [
"Veggies"
],
},
//etc for many key/values inside this object ..
}
I need to access the information do display a category ("Frozen Products" in this case) and all the product names and images under it.
But I think I need to access each Key/Value pair by loopin through their index (example data[0]) not the Key name since they keys are dynamically created by an API. So how can I change this to:
{
[ "Frozen Products": [
{
"_id": "6181849285e8d8f86be2d9df",
"name": "Peas (800g)",
"category_id": "6181841060c425f76e57b603",
"slug": "vegetables",
"quantity": 16,
"price": {
"amount": 3.00
},
"thumbnail":"URI ...",,
"images": [
"URI ...",
],
"synonyms": [
"Veggies"
],
},
]
I think you need something like this:
let data = {
"Frozen Products": [
{
"_id": "6181849285e8d8f86be2d9df",
...
}
],
"Another Category": [...]
}
let categories = Object.keys(data).map((key) => ({categoryName: key, products: data[key]}));
you can loop through an object with for in iterator.
No matter what key names are
for(key in object) {
let value = object[key];
}

How to find the value nested inside an array of objects

Here I have to get value of file_info, I tried doing it using array.includes and array.find(), but got undefined.
My confusion here is related to, under 'facts', the first value is "==", then it has array of values associated to it. I could not figure out to find the values inside that nested object.
I even tried array.find(facts).contains(fileinfo) that did not work as well.
How can I solve this ??
"data": [
{
"task-id": "126e7267",
"type": "A",
"output": {...}
},
{
"task-id": "bdfddff3",
"type": "B",
"output": {
"id": "12b54370",
"facts": [
{
"==": [
"A",
{
"#type": "AA",
"#value": {
"id": "12b54370-4594-4033-a299-5480b593ee6d",
"facts": [
{
"==": [
"time",
1575759643.904254
]
},
{
"==": [
"mime",
"text/plain"
]
},
{
"==": [
"owner",
1000
]
},
{
"==": [
"size",
100
]
},
{
"==": [
"file_info",
"a0s5b2e6e739" // have to find and return this value
]
},
{
"==": [
"time",
{
"#value": "2019-12-07T23:01:50.703Z",
"#type": "timestamp"
}
]
},
],
}
}
]
},
....
]
}
},
{
"task-id": "5f557eac",
"type": "C",
....
},
],
I have tried to validate your json string. It seems to be invalid. For answering this question , i would assume below string to be your json :
{"data":[{"task-id":"126e7267","type":"A","output":{}},{"task-id":"bdfddff3","type":"B","output":{"id":"12b54370","facts":[{"==":["A",{"#type":"AA","#value":{"id":"12b54370-4594-4033-a299-5480b593ee6d","facts":[{"==":[{"time":{"#value":"1575759643.904254"}}]},{"==":["mime","text/plain"]},{"==":["owner",1000]},{"==":["size",100]},{"==":[{"file_info":"a0s5b2e6e739"}]},{"==":["time",{"#value":"2019-12-07T23:01:50.703Z","#type":"timestamp"}]}]}}]}]}},{"task-id":"5f557eac","type":"C"}]}
I had tried to figure out a repetative pattern in your json but since "#value" tag is seen inside only one "facts" object below code should help you getting started . For given json , below code prints the value of "file_info"(Here , i'am assuming that "file_info" should be followed by a colon(:) i.e. "a0s5b2e6e739" is the value you are looking for) :
var jsonStr = '{"data":[{"task-id":"126e7267","type":"A","output":{}},{"task-id":"bdfddff3","type":"B","output":{"id":"12b54370","facts":[{"==":["A",{"#type":"AA","#value":{"id":"12b54370-4594-4033-a299-5480b593ee6d","facts":[{"==":[{"time":{"#value":"1575759643.904254"}}]},{"==":["mime","text/plain"]},{"==":["owner",1000]},{"==":["size",100]},{"==":[{"file_info":"a0s5b2e6e739"}]},{"==":["time",{"#value":"2019-12-07T23:01:50.703Z","#type":"timestamp"}]}]}}]}]}},{"task-id":"5f557eac","type":"C"}]}';
var jsonObj = JSON.parse(jsonStr);
//If there is a repetative pattern , you can replace this hard coding with your pattern.
var objArray = jsonObj["data"][1]["output"]["facts"][0]["=="][1]["#value"]["facts"];
console.log(objArray);
if(objArray && objArray.length >0){
for(let i =0;i<objArray.length;i++){
if(objArray[i] && objArray[i]["=="] && objArray[i]["=="].length > 0 && objArray[i]["=="][0]["file_info"]){
//here "file_info" is fetched
console.log('here ',objArray[i]["=="][0]["file_info"]);
}
}
}
Hope above code helps you to get started.
You can map and filter the object/array to get the result if the format is fixed. Here, I am writing to a Map and retrieving the property I need at the very end.
let data = [
{
"task-id": "126e7267",
"type": "A",
"output": {}
},
{
"task-id": "bdfddff3",
"type": "B",
"output": {
"id": "12b54370",
"facts": [
{
"==": [
"A",
{
"#type": "AA",
"#value": {
"id": "12b54370-4594-4033-a299-5480b593ee6d",
"facts": [
{
"==": [
"time",
1575759643.904254
]
},
{
"==": [
"mime",
"text/plain"
]
},
{
"==": [
"owner",
1000
]
},
{
"==": [
"size",
100
]
},
{
"==": [
"file_info",
"a0s5b2e6e739" // have to find and return this value
]
},
{
"==": [
"time",
{
"#value": "2019-12-07T23:01:50.703Z",
"#type": "timestamp"
}
]
},
],
}
}
]
}
]
}
},
{
"task-id": "5f557eac",
"type": "C",
"output": {}
}
]
const map = new Map()
const facts = data
.map(d => d.output)
.filter(o => o.hasOwnProperty('facts'))
.map(d => d.facts)
.map(i => i[0]["=="][1])
.map(d => d["#value"].facts)
const item = facts.forEach(o => o.forEach(i => map.set(i["=="][0], i["=="][1])))
console.log(map.get("file_info"))

Javascript parse JSON data into multiple variables storing separate records in memory

I have used JSON stringify and JSON Parse etc..., but I'm having trouble with finding /figuring how how to split up my JSON result into multiple variables.
Issue: I have a JSON result with 2 to many results (sections, pages etc...)
Goal : To store each result /row into its own variable.
Example of FULL unparsed JSON result:
{
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
}
]
},
{
"name": "page2",
"elements": [
{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}
]
}
]
}
In the example, notice that "name": "page1" and page2 are the clear separators, I could end up having them calling SectionA , SectionB etc.. but that shouldn't be important.
I need to store them separately
I also need to maintain that complete JSON structure
example of what i want to do with it
var page1 =
{
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
}
]
}
]
}
2nd one:
var page2 =
{
"pages": [
{
"name": "page2",
"elements": [
{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}
]
}
]
}
Notice that not only is it broken apart, but the main part I want to have maintained in the variable "pages: [
Just a simple map() operation would do it.
Afterwards you can use array destructuring to capture your result into separate variables:
const data = {
"pages": [{
"name": "page1",
"elements": [{
"type": "text",
"name": "question1"
}]
},
{
"name": "page2",
"elements": [{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}]
}
]
};
const split = data.pages.map(p => ({pages: [p]}));
console.log(split);
const [page1, page2] = split;
console.log(page1);
console.log(page2);

Flatten/Reduce nested JSON based on paths, collecting fields in path/hierarchy

UPDATE: 11/18/18: I've added more examples and clarification to the end of this post.
I have nested JSON structures, resulting from Elasticsearch aggregations, that look similar to this (simplified for the example):
{
"some_field": "ignore",
"buckets": [
{
"key": "a",
"buckets": [
{ "key": "foo", "name": "FOO" },
{ "key": "bar", "name": "BAR" }
]
},
{
"key": "b",
"buckets": [
{ "key": "boo", "name": "BOO" },
{ "key": "baa", "name": "BAA" }
]
}
]
}
I would like to convert it to
[
{key: "a", name: "FOO"},
{key: "a", name: "FOO"},
{key: "b", name: "BOO"},
{key: "b", name: "BAA"}
]
While this is a simple problem for any specific case, I don't want to "re-invent the wheel" and code for it each time. The level of nesting can vary and the fields I might pick (along the path) can vary.
The above is somewhat simplified example. As these come from Elasticsearch responses, another example might be:
"aggregations": {
"boo": {
"buckets": [
{
"key": "keyA",
"foo": {
"buckets": [
{
"key": "keyA.a",
"bar": {
"hits": {
"hits": [{"_index": "indexA", "_id": "idA", "_source": {"name": "nameA"}}]
}
}
}
]
}
},
{
"key": "keyB",
"foo": {
"buckets": [
{
"key": "keyA.a",
"bar": {
"hits": {
"hits": [{"_index": "indexB", "_id": "idB", "_source": {"name": "nameB"}}]
}
}
}
]
}
}
]
}
}
and my desired result, for flatten/picking fields is
[
{"boo": "keyA", "foo": "keyA.a", "name": "nameA", "id": "idA"},
{"boo": "keyB", "foo": "keyA.a", "name": "name", "id": "idB"}
]
Does anyone know of a way to do with JMESPath, JSONPath, lodash, etc? With something like JSONPath or JMESPath, I can select the "leaf" value easily, but I am trying to collect fields along the path, in the hierachy.
As noted, I could code each case, but I'd like to reuse a library and declare my projection.
I think I could do this with jq, but I need it to run in a browser.
Thanks
Lodash is useful in your case and can be used in a browser.
flapMap and map functions are what you need.
const _ = require('lodash');
var obj = {
"some_field": "ignore",
"buckets": [
{
"key": "a",
"buckets": [
{ "key": "foo", "name": "FOO" },
{ "key": "bar", "name": "BAR" }
]
},
{
"key": "b",
"buckets": [
{ "key": "boo", "name": "BOO" },
{ "key": "baa", "name": "BAA" }
]
}
]
};
var res = _.flatMap(obj.buckets, x => {
return _.map(x.buckets, y => {
y.key = x.key;
return y;
});
});
console.log(res);
// Output:
// [ { key: 'a', name: 'FOO' },
// { key: 'a', name: 'BAR' },
// { key: 'b', name: 'BOO' },
// { key: 'b', name: 'BAA' }]

Using lodash, how I can get the maximum length of nested array object

I need to take the data from below mentioned array of object which has maximum length of nested array object. As per below my request, id : 2 values has 3 objects, result will be as mentioned below.
Anyone help me using lodash or some javascript function to achieve this.
Sample Request:
[{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
Expected output:
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
This can be achieved using the native javascript reduce function as follows
var source = [...];
source.reduce((max, cur) => cur.values.length > max.values.length ? cur : max, source[0])

Categories