There is no "error" if you use more than one key with the same name, but in JSON, the last key with the same name is the one that is going to be used.
In your case, the key "name" would be better to contain an array as it's value, instead of having a number of keys "name". It doesn't make much sense the same object or "thing" to have two names, or two of the same properties that are in conflict.
E.g.:
{
"name" : [ "JOHN", "JACK", "...", ... ]
}
Answer from JeanK on Stack OverflowThere is no "error" if you use more than one key with the same name, but in JSON, the last key with the same name is the one that is going to be used.
In your case, the key "name" would be better to contain an array as it's value, instead of having a number of keys "name". It doesn't make much sense the same object or "thing" to have two names, or two of the same properties that are in conflict.
E.g.:
{
"name" : [ "JOHN", "JACK", "...", ... ]
}
From RFC 4627:
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string. A single colon comes after each name, separating the name from the value. A single comma separates a value from a following name. The names within an object SHOULD be unique.
You can use reduce() and concat() methods for this.
const data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]
// Use the `reduce` method to accumulate results into a single object.
const result = data.reduce(function(r, e) {
// Iterate over each key in the current object.
return Object.keys(e).forEach(function(k) {
// Check if the key exists in the result object.
if(!r[k]) r[k] = [].concat(e[k]) // If the key doesn't exist, initialize it as an array containing the value from the current object.
else r[k] = r[k].concat(e[k]) // If the key does exist, concatenate the existing array with the value from the current object.
}), r // Return the updated result object for the next iteration.
}, {}) // Start with an empty object `{}` as the initial value of `result`.
console.log(result)
You could use reduce method by passing a callback function as parameter.
The algorithm is follow: if final object already contains one key then you should initialize the key's value with an empty array. Otherwise, you should append to array value from all items from the array.
let data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]
let result = data.reduce(function(obj, item){
Object.keys(item).forEach(function(key){
if(!obj[key]) obj[key] = [].concat(item[key])
else {
if(Array.isArray(item[key]))
obj[key].push(...item[key])
else
obj[key].push(item[key]);
}
});
return obj;
},{});
console.log([result]);
You can use map like this :
EDIT
For handling generic keys you can use
Object.keys(d)[0] for first key
Object.keys(d)[1] for second key
var sample = [
{
"label":"one",
"value":1
},
{
"label":"two",
"value":2
},
{
"label":"three",
"value":3
},
{
"label":"four",
"value":4
},
{
"label":"five",
"value":5
}
];
var data = sample.map(function(d){
return {label: Object.keys(d)[0], value: Object.keys(d)[1], newKeyValue: Object.keys(d)[0] +"|" + Object.keys(d)[1]}
})
console.log(data)
Hope this helps!
You can use Array#map(), Object.keys(), and Array#join().
In ES6, you can use Arrow functions.
sample = sample.map(obj => {
var keys = Object.keys(obj);
obj.newKeyValue = keys.map(key => obj[key]).join('|');
return obj;
});
var sample = [{
"label": "one",
"value": 1
}, {
"name": "two",
"age": 2
}, {
"five": "three",
"six": 3
}, {
"company": "four",
"organization": 4
}, {
"label": "five",
"value": 5
}];
sample = sample.map(function (x) {
var keys = Object.keys(x);
x.newKeyValue = keys.map(key => x[key]).join('|');
return x;
});
console.log(sample);
document.body.innerHTML = '<pre>' + JSON.stringify(sample, 0, 4) + '</pre>';
In ES5, you can use the same code with anonymous functions
sample = sample.map(function (obj) {
var keys = Object.keys(obj);
obj.newKeyValue = keys.map(function (key) {
return obj[key]
}).join('|');
return obj;
});
Limitations due to dynamic keys:
- The order of the keys in object cannot be maintained
- This will join all the available keys in the object (in case if you just want to join fewer)
This is a job for .reduce().
const objArr = [
{name: 'Andrew', city: 'London'},
{name: 'Edouard', city: 'Paris'},
{name: 'Nathalie', city: 'London'},
{name: 'Patrick', city: 'London'},
{name: 'Mathieu', city: 'Paris'}
];
// Object of arrays
const result = objArr.reduce((acc, obj) => {
return {...acc, [obj.city]: [...acc[obj.city] || [], obj]}
}, {})
// Array of arrays
const result2 = Object.values(result);
console.log(result2)
Use lodash group by and then add to new array
var objArr = [ { name: 'Andrew', city: 'London' }, { name: 'Edouard', city: 'Paris' }, { name: 'Nathalie', city: 'London' }, { name: 'Patrick', city: 'London' }, { name: 'Mathieu', city: 'Paris' } ]
var grouped = _.mapValues(_.groupBy(objArr, 'city'),
clist => clist.map(city => _.omit(city, 'city')));
var result=[]
for (const [key, value] of Object.entries(grouped)) {
var array=[]
value.forEach(x=>{
array.push({ name: x.name, city:key })
})
result.push(array);
}
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
You can do:
const data = {data: [{name: 'A',description: {location: 'location1',floor: 'floor1',},},{name: 'A',description: {location: 'location2',floor: 'floor1',},},{name: 'B',description: {location: 'location3',floor: 'floor3',},},],}
const result = {
data: data.data.reduce((a, { name, description }) => {
const index = a.findIndex((d) => d.name === name)
if (index >= 0) {
let location = a[index].description.location
location = Array.isArray(location) ? location : [location]
a[index].description.location = [...location, description.location]
} else {
a.push({ name, description })
}
return a
}, []),
}
console.log(result)
const list = {
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
};
const consolidatedData = [];
for (const ele of list.data) {
const isExist = consolidatedData.find(x => x.name === ele.name);
if (!isExist) {
consolidatedData.push({
...ele
})
} else {
const objectKey = consolidatedData.findIndex(x => x.name === ele.name);
if (objectKey > -1) {
const description = consolidatedData[objectKey].description;
const newDes = ele.description;
if (newDes.location !== description.location) {
const data = consolidatedData[objectKey].description;
const added = [data.location, ele.description.location];
delete consolidatedData[objectKey].description.location
consolidatedData[objectKey].description["location"] = added
}
if (newDes.floor !== description.floor){
const data = consolidatedData[objectKey].floor;
const added = [data.floor, ele.description.floor];
delete consolidatedData[objectKey].description.floor
consolidatedData[objectKey].description["floor"] = added
}
}
}
}
console.log(JSON.stringify(consolidatedData, null, 2));
Use arrays:
{
"number": ["1", "2", "3"],
"alphabet": ["a", "b", "c"]
}
You can the access the different values from their position in the array. Counting starts at left of array at 0. myJsonObject["number"][0] == 1 or myJsonObject["alphabet"][2] == 'c'
{
"number" : ["1","2","3"],
"alphabet" : ["a", "b", "c"]
}
You can use first Array.reduce() to group the companies by the module key on a Set. On a second step you can use array.Map() over the generated object .entries() to get the final desired result:
const data = [
{module: "credit_cards", id: "1", company: "ABC", prod: "1"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "credit_cards", id: "3", company: "EFG", prod: "2"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "mortgages", id: "4", company: "EFG", prod: "3"}
];
let res = data.reduce((acc, {module, company}) =>
{
acc[module] = acc[module] || new Set();
acc[module].add(company);
return acc;
}, {})
res = Object.entries(res).map(
([module, companies]) => ({module, company: [...companies]})
);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Reduce into an object indexed by module, then take that object's values. Because you only want unique company values, use a Set initially, and then transform all items' company sets back into an array afterwards:
const data = [
{module: "credit_cards", id: "1", company: "ABC", prod: "1"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "credit_cards", id: "3", company: "EFG", prod: "2"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "mortgages", id: "4", company: "EFG", prod: "3"}
]
const result = Object.values(data.reduce(
(a, { module, company }) => {
if (!a[module]) a[module] = { module, company: new Set() };
a[module].company.add(company);
return a;
},
{}
));
result.forEach((item) => {
item.company = [...item.company];
});
console.log(result);
Hi - I'm quite new to python and attempting to parse some json, reasonably unsuccessfully at the moment. I have the following structure:
json_data = {
"struct": [[
{
"struct": "car",
"points": {
"brand": "tesla",
"points": {
"engine_size": "electric",
"doors": "2",
"points": {
"colour": "83922",
}
}
}
},
{
"struct": "house",
"points": {
"house_type": "semi",
"windows": "6"
}
},
{
"struct": "garden",
"points": {
"garden_type": "small"
}
}
]]}
For each structure or 'struct' I'm trying to pull out only the points, but not nested points if that makes sense? So the end results should print out:{'brand': 'tesla', 'points'}{'engine_size': 'electric', 'doors': '2'}{'colour': '83922'}{'house_type': 'semi', 'windows': '6'}{'garden_type': 'small'}
I can parse some of this quite easily, but i am struggling with the car details. The best i can get is :{'brand': 'tesla', 'points': {'engine_size': 'electric', 'doors': '2', 'points': {'colour': '83922'}}}{'engine_size': 'electric', 'doors': '2', 'points': {'colour': '83922'}}{'colour': '83922'}{'house_type': 'semi', 'windows': '6'}{'garden_type': 'small'}
But i dont want the nested points - i need each 'points' separate, my working code right now is:
def print_points(data):
if isinstance(data, dict):
for key, value in data.items():
if key == 'points':
print(value)
print_points(value)
else:
print_points(value)
elif isinstance(data, list):
for item in data:
print_points(item)print_points(json_data)
Can anyone offer any suggestions / articles / guidance as to how I can learn how to do this? I'm not very good with data structures yet!
You need to use JSON.deserialiseUntyped and get the values from it:
Map<String,Object> jsonMap = (Map<String,Object>)JSON.deserializeUntyped('{"AccountId":"00128000009j45sAAA","email":"email1, email2, email3"}');
List<String> emailList = ((String)jsonMap.get('email')).split(',');
List<Contact> cons = new List<Contact>();
String accId = (String)jsonMap.get('AccountId');
for(String em : emailList) {
cons.add(new Contact(AccountId=accId, Email=em.trim()));
}
System.debug('cons => '+cons);
Note: 0014000001aasdfAA mentioned in your JSON is not a valid Id. You need to check that.
an alternative using custom apex types with deserialization support
class AccountWithEmails {
Id AccountId;
String email;
}
AccountWithEmails awe =
(AccountWithEmails) JSON.deserialize(myHttpResponse.getBody(),AccountWithEmails.class);
Contact[] contacts = new List<Contact>();
for (String email: awe.email.split(',') ){
contacts.add(new Contact(AccountId = awe.AccountId, Email = email, LastName = ..));
}
insert contacts;