Edit JSON data structure using JS - javascript

The original JSON file:
{
"data": {
"count_at_hub": [
{
"hub": "A",
"date": "",
"size": "1",
"count": 141
},
{
"hub": "A",
"date": "",
"size": "2",
"count": 44
},
{
"hub": "A",
"date": "",
"size": "3",
"count": 3
},
{
"hub": "A",
"date": "",
"size": "0",
"count": 1446
},
{
"hub": "B",
"date": "",
"size": "1",
"count": 202
},
{
"hub": "B",
"date": "",
"size": "0",
"count": 2082
},
{
"hub": "B",
"date": "",
"size": "3",
"count": 11
},
{
"hub": "B",
"date": "",
"size": "2",
"count": 53
}
],
"Part B":[
{
}
]
},
"success": true,
"errors": [],
"e": {}}
I want to change the structure to:
{
"data": {
"count_at_hub": [
{
"hub": "A",
"date": "",
"size1": 141,
"size2": 44,
"size3": 3,
"size4": 1446
},
{
"hub": "B",
"date": "",
"size1": 202,
"size2": 2082,
"size3": 11,
"count": 53
}
],
"Part B":[
{
}
]
},
"success": true,
"errors": [],
"e": {}}
Basically, I want to put all the count of the same hub under the same array. How do I come about doing this?
In terms of huge amount of data, will changing the JSON to the new file make the loading speed longer as compared to making JS looping through the original file to build a dashboard?

You can iterate and take an object as reference to the result array.
The elements of size": "0" go to size4.
var object = { "data": { "count_at_hub": [{ "hub": "A", "date": "", "size": "1", "count": 141 }, { "hub": "A", "date": "", "size": "2", "count": 44 }, { "hub": "A", "date": "", "size": "3", "count": 3 }, { "hub": "A", "date": "", "size": "0", "count": 1446 }, { "hub": "B", "date": "", "size": "1", "count": 202 }, { "hub": "B", "date": "", "size": "0", "count": 2082 }, { "hub": "B", "date": "", "size": "3", "count": 11 }, { "hub": "B", "date": "", "size": "2", "count": 53 }], "Part B": [{}] }, "success": true, "errors": [], "e": {} },
temp = [];
object.data.count_at_hub.forEach(function (a) {
if (!this[a.hub]) {
this[a.hub] = { hub: a.hub, date: a.date, size1: 0, size2: 0, size3: 0, size4: 0 };
temp.push(this[a.hub]);
}
this[a.hub]['size' + (+a.size || 4)] += a.count;
}, Object.create(null));
object.data.count_at_hub = temp;
console.log(object);

Hi this is my answer according to my proposal with sizes array in which each size.count is located at the index corresponding to the size value. i.e. size: 0 count : 2082 is placed like [2082,,,] in the array. To access the size and count you can do like count = sizes[size] The code is as follows;
var cag = [
{
"hub": "A",
"date": "",
"size": "1",
"count": 141
},
{
"hub": "A",
"date": "",
"size": "2",
"count": 44
},
{
"hub": "A",
"date": "",
"size": "3",
"count": 3
},
{
"hub": "A",
"date": "",
"size": "0",
"count": 1446
},
{
"hub": "B",
"date": "",
"size": "1",
"count": 202
},
{
"hub": "B",
"date": "",
"size": "0",
"count": 2082
},
{
"hub": "B",
"date": "",
"size": "3",
"count": 11
},
{
"hub": "B",
"date": "",
"size": "2",
"count": 53
}
],
reduced = cag.reduce((p,c) => (p[c.hub] ? p[c.hub].sizes[c.size] = c.count
: p[c.hub] = { "hub": c.hub,
"date": c.date,
"sizes": (new Array(c.size*1)).concat(c.count)},
p),{}),
result = Object.keys(reduced).map(k => reduced[k]);
console.log(result);
I first construct a reduced object which can also be used for your purposes but then i map this object into an array so that the data is in the array of objects form. You can use whichever form of data you like the best.
The slightly confusing part might be the (new Array(c.size*1)).concat(c.count) instruction. There we are creating a new object (through object literal) and we have to initiate a sparse sizes array with only one value inserted at the index position designated by the size value. So we construct a new Array of size (new Array(c.size*1)) however our c.size value is of string type. If we do like new Array("2") then we will receive an array with one string item ("2") at index 0. But we want an array in the size of 2. That's why we convert string "2" to number 2 by "2"*1 operation (multiplication operator type coerces string into number). So we receive an empty array of size 2. Now comes the concat operation which attaches our size value to the correct index location in the resulting array.
It's essentially the unification of the following two instructions
var sizes = [];
sizes[c.size] = c.count;

Related

How to convert items that are returned as an XML string rather than JSON?

I am having the following issue :
BE is returning a JSON file that has keys and values but some values are in XML format. How can I turn them into JSON as well ?
It's the first time I am seeing this kind of structure. So any help would be appreciated. I am working on in a React environment.
[{
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": [
{
"size": "regular",
"coating": "none",
"amount": 8
},
{
"size": "regular",
"coating": "CBD",
"amount": 4
}
]
},
{
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>regular</size><coating>none</coating><amount>10</amount></item><item><size>regular</size><coating>CBD</coating><amount>2</amount></item></items>"
},
{
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": [
{
"size": "small",
"coating": "none",
"amount": 8
},
{
"size": "small",
"coating": "CBD",
"amount": 4
}
]
},
{
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>small</size><coating>none</coating><amount>10</amount></item><item><size>small</size><coating>CBD</coating><amount>2</amount></item></items>"
},
{
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>regular</size><coating>none</coating><amount>12</amount></item></items>"
},
{
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>small</size><coating>none</coating><amount>12</amount></item></items>"
}]
Ideally it should be corrected at backend itself but still if you don't have a control on backend and want to parse it in frontend only. You can simply achieve this requirement with the help of DOMParser API.
Live Demo :
const inputArr = [{
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": [
{
"size": "regular",
"coating": "none",
"amount": 8
},
{
"size": "regular",
"coating": "CBD",
"amount": 4
}
]
}, {
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>regular</size><coating>none</coating><amount>10</amount></item><item><size>regular</size><coating>CBD</coating><amount>2</amount></item></items>"
}, {
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": [
{
"size": "small",
"coating": "none",
"amount": 8
},
{
"size": "small",
"coating": "CBD",
"amount": 4
}
]
}, {
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>small</size><coating>none</coating><amount>10</amount></item><item><size>small</size><coating>CBD</coating><amount>2</amount></item></items>"
}, {
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>regular</size><coating>none</coating><amount>12</amount></item></items>"
}, {
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"items": "<items><item><size>small</size><coating>none</coating><amount>12</amount></item></items>"
}];
const itemKeys = ['size', 'coating', 'amount'];
function parseXMLString(arr, itemKeys) {
const parser = new DOMParser();
arr.forEach((o, index) => {
const a = [];
if (typeof o.items === 'string') {
const xmlParsedStr = parser.parseFromString(o.items, "text/xml");
itemKeys.forEach(item => {
const itemKeysArr = xmlParsedStr.getElementsByTagName(item);
for (let i=0; i < itemKeysArr.length; i++) {
for (let j=0; j < itemKeysArr[i].childNodes.length; j++) {
a[i] ? a[i][item] = itemKeysArr[i].childNodes[j].nodeValue :
a[i] = { [item]: itemKeysArr[i].childNodes[j].nodeValue }
}
}
})
arr[index].items = a;
}
});
return arr;
}
console.log(parseXMLString(inputArr, itemKeys));
Using https://www.npmjs.com/package/xml-js makes this a easy task
const convert = require('xml-js');
function convertItems(item) {
if (typeof item.items === 'string') {
const options = {compact: true, ignoreComment: true, spaces: 4};
const result = convert.xml2json(item.items, options);
const itemDetails = JSON.parse(result);
item["details"] = itemDetails.items.item;
delete item.items;
} else {
item["details"] = item.items;
delete item.items;
}
return false;
}
for (let i = 0; i < data.length; i++) {
convertItems(data[i]);
}
console.log(JSON.stringify(data, null, 4));
output:
[
{
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": [
{
"size": "regular",
"coating": "none",
"amount": 8
},
{
"size": "regular",
"coating": "CBD",
"amount": 4
}
]
},
{
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": [
{
"size": {
"_text": "regular"
},
"coating": {
"_text": "none"
},
"amount": {
"_text": "10"
}
},
{
"size": {
"_text": "regular"
},
"coating": {
"_text": "CBD"
},
"amount": {
"_text": "2"
}
}
]
},
{
"price": 19,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": [
{
"size": "small",
"coating": "none",
"amount": 8
},
{
"size": "small",
"coating": "CBD",
"amount": 4
}
]
},
{
"price": 18,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": [
{
"size": {
"_text": "small"
},
"coating": {
"_text": "none"
},
"amount": {
"_text": "10"
}
},
{
"size": {
"_text": "small"
},
"coating": {
"_text": "CBD"
},
"amount": {
"_text": "2"
}
}
]
},
{
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": {
"size": {
"_text": "regular"
},
"coating": {
"_text": "none"
},
"amount": {
"_text": "12"
}
}
},
{
"price": 17,
"currency": "GBP",
"productImage": "https://daye.cdn.prismic.io/daye/ee153f6163435330b18495535217c531300382a8_product2x.png",
"details": {
"size": {
"_text": "small"
},
"coating": {
"_text": "none"
},
"amount": {
"_text": "12"
}
}
}
]

How to compare 2 nested json objects arrays Javascript

I am trying to compare 2 nested json objects arrays using lodash. Following example will return true even obj1 and obj2 have different number of objects inside the array.
Basically what I need to do is compare these 2 nested json objects arrays and if the arrays are identical then needs to return true else false
note : obj1 has price element and obj2 has countInStock which should not use to compare
Can anyone help me to solve this?
import _ from "lodash"
var obj1 = [{
"colour": {
"value": "Black",
"label": "Black"
},
"size": {
"value": "M",
"label": "M"
},
"price": "70"
},
{
"colour": {
"value": "Black",
"label": "Black"
},
"size": {
"value": "M",
"label": "M"
},
"price": "70"
},
{
"colour": {
"value": "Silver",
"label": "Silver"
},
"size": {
"value": "S",
"label": "S"
},
"price": "50"
},
{
"colour": {
"value": "Black",
"label": "Black"
},
"size": {
"value": "L",
"label": "L"
},
"price": "130"
}]
var obj2 = [{
"colour": {
"value": "Silver",
"label": "Silver"
},
"size": {
"value": "S",
"label": "S"
},
"countInStock": "3"
},
{
"colour": {
"value": "Black",
"label": "Black"
},
"size": {
"value": "M",
"label": "M"
},
"countInStock": "10"
},
{
"colour": {
"value": "Black",
"label": "Black"
},
"size": {
"value": "L",
"label": "L"
},
"countInStock": "3"
}]
var result = _.isEqual(
_.omit(obj1.sort, ['price']),
_.omit(obj2.sort, ['countInStock'])
);
console.log(result); // true

Unnest Javascript Array into JSON

I have created a Javascript array that I need to reformat into Json so that I can display it in a table.
I am trying to take the following javascript array:
[
{
"name": "ticker",
"value": "V"
},
{
"name": 5,
"value": -0.09453565931246788
},
{
"name": 10,
"value": -0.08185562540645996
},
{
"name": 90,
"value": -0.1023591207807445
},
{
"name": 120,
"value": -0.03745328055393815
},
{
"name": 250,
"value": 0.13101799630844946
}
]
And transform it into:
const myTableData = [
{"name": "ticker", "value": V},
{"name": "5", "value": -0.09453565931246788},
{"name": "10", "value": -0.08185562540645996},
{"name": "90", "value": -0.1023591207807445},
{"name": "120", "value": -0.03745328055393815},
{"name": "250", "value": 0.13101799630844946}
];
How can I do this?
Just use JSON.stringify
var myArray = [
{
"name": "ticker",
"value": "V"
},
{
"name": 5,
"value": -0.09453565931246788
},
{
"name": 10,
"value": -0.08185562540645996
},
{
"name": 90,
"value": -0.1023591207807445
},
{
"name": 120,
"value": -0.03745328055393815
},
{
"name": 250,
"value": 0.13101799630844946
}
];
var myJsonString = JSON.stringify(myArray);
console.log(myJsonString);

Javascript : sorting an object by child object given key value

How to sort an object by a given value of its child keys ?
For instance, this object:
{
"a": {
"name": "Edward",
"value": 21
},
"b": {
"name": "Sharpe",
"value": 37
},
"c": {
"name": "And",
"value": 45
},
"d": {
"name": "The",
"value": -12
},
"e": {
"name": "Magnetic",
"value": 13
},
"f": {
"name": "Zeros",
"value": 37
}
}
would become sorted by the "value" key of its child objects:
{
"d": {
"name": "The",
"value": -12
},
"e": {
"name": "Magnetic",
"value": 13
},
"a": {
"name": "Edward",
"value": 21
},
"b": {
"name": "Sharpe",
"value": 37
},
"f": {
"name": "Zeros",
"value": 37
},
"c": {
"name": "And",
"value": 45
}
}
This works
var obj = {
"a": {
"name": "Edward",
"value": 21
},
"b": {
"name": "Sharpe",
"value": 37
},
"c": {
"name": "And",
"value": 45
},
"d": {
"name": "The",
"value": -12
},
"e": {
"name": "Magnetic",
"value": 13
},
"f": {
"name": "Zeros",
"value": 37
}
};
const result = Object.fromEntries(Object.entries(obj).sort(([,{value:a}],[,{value:b}])=>a-b));
console.log(result);
console.log(Object.keys(result).join());
but while this seems to work, object property order is not strictly defined, so whose to say it will always work
for example, if some of the top level keys are numeric, this is the result
var obj = {
"a": {
"name": "Edward",
"value": 21
},
"b": {
"name": "Sharpe",
"value": 37
},
"1": {
"name": "And",
"value": 45
},
"d": {
"name": "The",
"value": -12
},
"2": {
"name": "Magnetic",
"value": 13
},
"f": {
"name": "Zeros",
"value": 37
}
};
const result = Object.fromEntries(Object.entries(obj).sort(([,{value:a}],[,{value:b}])=>a-b));
console.log(result);
console.log(Object.keys(result).join()); // want d2abf1 - get 12dabf
this is because numeric keys ALWAYS precede non-numeric, regardless of creation order - thats one thing that IS defined about object property order

manipulating JSON array data

I have a JSON array from DB, and I want it to manipulate. Currently it has discreet 8 elements, I want the array to manipulate it to get 2 elements, rest elements will be nested. My current JSON has this structure:
{
"itemId": 1,
"desc": [{
"type": "A",
"size": "xx",
"count": 12,
"price": 122
},
{
"type": "A",
"size": "xl",
"count": 18,
"price": 180
},
{
"type": "B",
"size": "xx",
"count": 12,
"price": 122
},
{
"type": "B",
"size": "xl",
"count": 12,
"price": 122
}]
}
I want the data to be manipulated to come like this:
{
"type": "A",
"desc":{
"size": "xx",
"count": 12,
"price": 122
},
{
"size": "xl",
"count": 12,
"price": 122
},
},
{
"type": "B",
"desc":{
"size": "xx",
"count": 12,
"price": 122
},
{
"size": "xl",
"count": 12,
"price": 122
},
}
I am using for each loop, but this is creating individual elements, i want just two elements in the resulting array.
Any solution will be appreciated.
You could try something like this:
var new_data = {
A: {type: 'A', desc: []},
B: {type: 'B', desc: []}
};
$.each(data.desc, function( index, value ) {
new_data[value.type].desc.push(value);
});
https://jsfiddle.net/5cnaxn04/
If you don't know the types you will get, you can build the object dynamically:
var new_data = {};
$.each(data.desc, function( index, value ) {
if(typeof new_data[value.type] === "undefined") {
new_data[value.type] = {type: value.type, desc: [value]}
} else {
new_data[value.type].desc.push(value);
}
});
https://jsfiddle.net/5cnaxn04/1/
You have some syntax errors in your code, as you are using {} for both Arrays and Objects, so I'd guess from the context. You need a few loops to make the data look exactly to what you want.
See JSFiddle.

Categories