The JSON provided is kind of unstructured and doesn't meet many of my
requirements. I have tried this many ways but does take a very long time
when I provide 100,000 records
Implemented Code
for (var f in stack.data) {
var field = new Object();
for (var o in stack.data[f]['field_values']) {
field[stack.data[f]['field_values'][o]['field_name']] = stack.data[f]['field_values'][o]['value'];
}
stack.data[f]['field_values'] = field;
}
console.log(JSON.stringify(stack, null, 2));
Input JSON:
var stack = {
"data": [{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": [{
"field_name": "Newsletter?",
"value": true
},
{
"field_name": "Parent",
"value": 950888661
},
{
"field_name": "Birthday",
"value": "2018-04-29"
},
{
"field_name": "Related matter",
"value": 1055396205
},
{
"field_name": "Referral",
"value": "Don Ho"
},
{
"field_name": "Spouse",
"value": "Wo Fat"
}
]
}]
}
Expected Output:
{
"data": [
{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": {
"Newsletter?": true,
"Parent": "Gigi Hallow",
"Birthday": "2018-04-29",
"Related": "2012-00121-Sass",
"Referral": "Don Ho",
"Spouse": "Wo Fat"
}
Sometimes "field_values can be empty. Need to check them as well
{
"id": 950821118875,
"name": "www.google.com",
"field_values": [],
}
This is mostly re-arranging the values. Here values becomes keys. There should actually be one liner to handle this, but i am run out of options.
Hope the question is clear
It would probably help to declare a variable to hold the array element, rather than doing 4 levels of indexing every time through the loop. You can also use destructuring to extract the properties of the object.
And use {} rather than new Object.
Even if this doesn't improve performance, it makes the code easier to read.
var stack = {
"data": [{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": [{
"field_name": "Newsletter?",
"value": true
},
{
"field_name": "Parent",
"value": 950888661
},
{
"field_name": "Birthday",
"value": "2018-04-29"
},
{
"field_name": "Related matter",
"value": 1055396205
},
{
"field_name": "Referral",
"value": "Don Ho"
},
{
"field_name": "Spouse",
"value": "Wo Fat"
}
]
}]
}
for (var f in stack.data) {
const field = {};
const fobj = stack.data[f];
for (var o in fobj.field_values) {
const {field_name, value} = fobj.field_values[o];
field[field_name] = value;
}
fobj.field_values = field;
}
console.log(JSON.stringify(stack, null, 2));
Related
Trying to get my head around this one..
Incoming data looks like:
[
{
"value": {
"label": "MZ Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Lionel Carter"
}
},
{
"value": {
"label": "BW Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Jerome Yost"
}
},
{
"value": {
"label": "Detergent",
"type": "case",
"incident": null,
"personName": "Jerald Legros"
}
}
]
I would like to transform this into
[
{
"label": "Algal bloom",
"children": [
{ "label": "Lionel Carter", "type": "case"},
{ "label": "Jerome Yost", "type": "case" }]
},
{ "label": "Detergent", "type": "case" }
]
Basically, the rule is that if incident is not NULL then the incident name becomes the parent and the children hold the personName - otherwise we simply pass through the label and type. I can walk the array and switch out the label with the incident name, but I'm not sure how to group up the incidents..
It's basic grouping with an exception for elements without incident.
You can group the elements without incident in a separate group:
const data = [{"value": {"label": "MZ Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Lionel Carter"}},{"value": {"label": "BW Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Jerome Yost"}},{"value": {"label": "Detergent","type": "case","incident": null,"personName": "Jerald Legros"}}];
function group(data) {
const result = data.reduce((acc, { value }) => {
if (!value.incident) {
acc.ungrouped.push({ label: value.label, type: value.type });
} else {
if (!acc.groups[value.incident.name]) acc.groups[value.incident.name] = { label: value.incident.name, children: [] };
acc.groups[value.incident.name].children.push({ label: value.personName, type: value.type });
}
return acc;
}, { groups: {}, ungrouped: [] });
return [...Object.values(result.groups), ...result.ungrouped];
}
console.log(group(data));
I have an array as under
Data =
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
}
]
},
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
Data array has two objects. I want to merge the aggregate property of second object in the first one.
something like this:
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
is there any way to implement this. Level of nesting is dynamic but all the objects will have same structure.
To merge the 2 objects inside the array into 1, this involves
Step 1. extracting the required elements from the 2nd object
Step 2. adding it into the object of the first.
Suppose the array is read into a variable data, then this is 1 way we can extract it in Step 1.
let {
aggregates: {
VALVAL_ALT_CMB_AMT
},
} = data[1];
The value paired to the VALVAL_ALT_CMB_AMT key of the 2nd object is stored inside a variable VALVAL_ALT_CMB_AMT. You can read more about Object Destructuring in Javascript.
For Step 2, we will add the value into the first variable. We can also think of objects to have similar syntax to maps, hence this is 1 way we can do it.
let first = data[0];
first["aggregates"]["VALVAL_ALT_CMB_AMT_1"] = VALVAL_ALT_CMB_AMT;
Extracting and adding the elements this way forms a shallow copy of the variable VALVAL_ALT_CMB_AMT, now as a value of VALVAL_ALT_CMB_AMT_1. Consequently, it is not advisable to delete the actual object in position 1 from the original array. Instead, it might be better to return the new object first in a new array.
const result = [first];
return result;
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
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.
I have the following JSON object. Using JQuery I need to find the values of the following:
summary.nameValues.ID and detail.TypedNameValues.size
Could somebody please show how this can be achieved using JQuery?
[
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": [
"232639"
]
},
{
"Name": "City",
"Values": [
"London"
]
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
]
jQuery doesn't work on plain object literals. You can use the below function in a similar way to search all 'id's (or any other property), regardless of its depth in the object:
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
Use like so:
getObjects(TestObj, 'id', 'A'); // Returns an array of matching objects
This answer taken from another thread. You may find more help here: use jQuery's find() on JSON object
Performing this kind of queries on JSON structures are trivial using DefiantJS (http://defiantjs.com). This lib extends the global object JSON with the method "search" - with which one can execute XPath expressive searches.
Check out this fiddle;
http://jsfiddle.net/hbi99/kLE2v/
The code can look like this:
var data = [
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": "232639"
},
{
"Name": "City",
"Values": "London"
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
],
res = JSON.search( data, '//*[Name="size"]' );
console.log( res[0].Value );
// 434353
Some one else as already answered, either way here is my version for the same.
<textarea id="ta" style="display:none;">[
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": [
"232639"
]
},
{
"Name": "City",
"Values": [
"London"
]
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
]</textarea>
Parser
var obj = $.parseJSON($('#ta').val());
var nameValues = obj[0].summary.NameValues;
var typedNameValues = obj[0].detail.TypedNameValues;
function getObjByName(o, name) {
for (var i = 0; i < o.length; i++) {
if (o[i].Name == name) {
return o[i];
}
}
return null;
}
alert(getObjByName(nameValues, 'Id').Values.join(", "));
alert(getObjByName(typedNameValues, 'size').Value);
A working fiddle for you on the same.
http://jsfiddle.net/3EVE4/