Get JSON keys in order - javascript

I have the below in a file and read as
var input = require("./mydata.json");
"User": {
"properties": {
"firstName": {
"type": "string",
"minLength": 1,
"maxLength": 50
},
"lastName": {
"type": "string",
"maxLength": 50
},
"middleName": {
"type": "string"
},
"title": {
"type": "string"
},
"language": {
"type": "string",
"default": "en-US"
}
}
}
I am using the below code to loop through the keys
var item = _.get(input, 'User');
var properties = item.properties;
var allKeys = _.keys(properties);
_.each(allKeys, function(key) {
});
Inside the each loop, I get the firstname, lastname etc, in the same sequence as in the input file.
I want to know if I will get it in order always?

Properties order in objects is not guaranteed in JavaScript; you need to use an Array to preserve it.
Definition of an Object from ECMAScript Third Edition (pdf):
4.3.3 Object
An object is a member of the
type Object. It is an unordered collection of properties each of which
contains a primitive value, object, or
function. A function stored in a
property of an object is called a
method.
Since ECMAScript 2015, using the Map object could be an alternative. A Map shares some similarities with an Object and guarantees the keys order:
A Map iterates its elements in insertion order, whereas iteration order is not specified for Objects.

Yes, If you want to change the order then you will need to sort or arrange the keys in a separate array and then loop on rearranged array.

Object.keys(input.User).sort();
// Will return all keys in sorted array.
Then , if you want to read value of each key following that order , just loop through that array :
Object.keys(input.User).sort().forEach((key,index)=>{
console.log('key :'+key+' , value :'+input.User[key]);
})

Related

Retrieve object with a key in javascript

I have following object, and if I want to retrieve only soccer, then I put soccer as follows,
sports['soccer'] does not bring it.
I wonder what I am missing here?
sports = [] ;
sports = [{
"soccer": {
"type": "foot",
"player": 11
},
"basketball": {
"type": "hand",
"player": 5
}
}]
Your current code creates an array with a single object. One solution is to just create an object instead:
sports = {
"soccer": {
"type": "foot",
"player": 11
},
"basketball": {
"type": "hand",
"player": 5
}
}
Now you can use sports.soccer or sports['soccer'] to access the soccer data.
If you really want an array of objects, you first need to subscript the array to get the first object:
sports[0].soccer
or
sports[0]['soccer']
var sports is an array with objects inside.
If you set it up like this:
sports = [] ;
sports = {
"soccer": {
"type": "foot",
"player": 11
},
"basketball": {
"type": "hand",
"player": 5
}
}
then you will be able to call sports['soccer'] or even sports.soccer.
Alternately, if you need it to remain an array, then you'll need to do more work.
Something like this should do the trick.
for(i=0; i < sports.length; i++) {
if("soccer" in sports[i]){
console.log(sports[i].soccer.type);
console.log(sports[i].soccer.player);
}
}
The console.logs represent whatever you want to do with the values
I think you really need to reiterate the basics of javascript a bit.
In JS we can create data structures on the fly with literal syntax. For example:
let normalArr = new Array();
let literalArr = [];
let normalObj = new Object();
let literalObj = {};
When you create arrays and objects with literal syntax you can initialize arrays with elements and object with properties on the fly. This is what exactly happened in your example:
sports = [{
"soccer": {
"type": "foot",
"player": 11
},
"basketball": {
"type": "hand",
"player": 5
}
}];
The code can be broken down in the following way:
You created an array which was stored in the sports variable using the array literal syntax (created an array on the fly).
You created 1 element of the array with the object literal syntax (creating an object on the fly)
This object (located inside the array) has 2 properties, soccer and basketball which are also object created with object literal syntax.
To access one of there objects you need to do the following:
const sports = [{
"soccer": {
"type": "foot",
"player": 11
},
"basketball": {
"type": "hand",
"player": 5
}
}];
// accessing the first element of the sports array
console.log(sports[0].soccer);
console.log(sports[0].basketball);
As others have pointed out, you have an array of objects, not a single object. You can use the find() method to find the element that has the soccer property, and then access that property.
var soccer = sports.find(s => 'soccer' in s)['soccer'];

Javascript create an object, keyed by array value

I have a method which needs to return a user object from a supplied id parameter. Further methods will use this structure so it's not a simple case of using the existing structure.
Essentially I have a database which contains a type key, this is filtered so that I have a collection of users. What I need to do is create an object which is keyed by the users _id value and contains the users object with the _id and type omitted.
Using lodash or some ES6 sugar I would like to transform the following Array;
[
{
"_id": "0e12e661cb50068a135b36067f001d20",
"name": "Joe Bloggs",
"type": "user"
},
{
"_id": "0e12e661cb50068a135b36067f00373f",
"name": "Ben Bloggs",
"type": "user"
}
]
Into the following Object, with the _id and type omitted;
{
"0e12e661cb50068a135b36067f001d20": {
"name": "Joe Bloggs"
},
"0e12e661cb50068a135b36067f00373f": {
"name": "Ben Bloggs"
}
}
EDIT I need to return the object and NOT the name as further properties could be added to these objects.
You can do this with just reduce().
var data = [{
"_id": "0e12e661cb50068a135b36067f001d20",
"name": "Joe Bloggs",
"type": "user"
}, {
"_id": "0e12e661cb50068a135b36067f00373f",
"name": "Ben Bloggs",
"type": "user"
}]
var result = data.reduce(function(r, e) {
r[e._id] = {name: e.name};
return r;
}, {})
console.log(result)
ES6 version with arrow function
var result = data.reduce((r, e) => (r[e._id] = {name: e.name}, r), {})
Update: To just exclude specific properties from new object you can use Object.assign() DEMO to create copy of object and then delete to delete some properties or you can use forEach() loop and add properties that you want DEMO

Keep order of objects inside a JSON String after they are parsed

I receive the following JSON string from an API function.
"Inbound": {
"callRelatedFields": ["ANI",
"DNIS"],
"objects": {
"Contact": [{
"displayName": "Name",
"apiName": "Name"
},
{
"displayName": "Email",
"apiName": "Email"
}],
"Account": [{
"displayName": "Account Name",
"apiName": "Name"
},
{
"displayName": "Phone",
"apiName": "Phone"
},
{
"displayName": "Fax",
"apiName": "Fax"
}],
"cnx__Phone__c": [{
"displayName": "Phone Name",
"apiName": "Name"
},
{
"displayName": "Phone Number Line 1",
"apiName": "cnx__Phone_Number_Line_1__c"
},
{
"displayName": "Phone Number Line 2",
"apiName": "cnx__Phone_Number_Line_2__c"
},
{
"displayName": "Type",
"apiName": "cnx__Type__c"
},
{
"displayName": "Location",
"apiName": "cnx__Location__c"
},
{
"displayName": "Call Manager",
"apiName": "cnx__Call_Manager__c"
},
{
"displayName": "Mac Address",
"apiName": "cnx__Mac_Address__c"
}]
},
"screenPopSettings": {
"screenPopsOpenWithin": "ExistingWindow",
"SingleMatch": {
"screenPopType": "PopToEntity"
},
"NoMatch": {
"screenPopType": "DoNotPop"
},
"MultipleMatches": {
"screenPopType": "DoNotPop"
}
}
}
The order of the objects inside "objects" is important!
But when i parse this JSON string with JSON.parse, the order of those objects is lost.
Is there any good way to keep the order of those objects after they are parsed.
I tried to manipulate the string and convert the whole "objects" into an array, but this turned out to become way too complicated and hacky.
I have a suspicion that the thing that makes you think the keys have changed order is that Chrome devtools show objects with their keys sorted in alphabetical order. Whereas if you use Object.keys() or the equivalent JS to manually iterate through the keys, you will find they come out in the order they were defined in the JSON string.
Here is the equivalent JS for Object.keys():
function objectKeys(obj) {
var keys = [];
if (!obj) return keys;
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
}
}
}
When I call this with the objects part of the parsed object I get the following array:
["Contact", "Account", "cnx__Phone__c"]
Unfortunately object properties are unordered in JavaScript so you shouldn't rely on being able to iterate over them in a particular sequence.
I would suggest accessing the properties by name in the order you need them, rather than just iterating over the list.
As per the JSON standard, an object is unordered. So if you care about the order "Contact", "Account", "cnx__Phone__c", put them in an array ([]).
Maybe it's enough to put the property names themselves in an array next to the .objects themselves, so that you still can access them by their names. Many structures are valid solutions.
This solution works only if the properties and the data does not contain one of these characters: {, } and :.
Maybe you replace the curly brackets to square brackets and ": to #",. After that, you can the JSON string parse and get all objects replaced by arrays. The reading is: first value is the property (marked with # at the end) and the second value is the value.
The replacement machanism shuld be improved, in particular the replacement of ":, which can sometimes be wrong, and the search of the curly brackets.
var json = '{"Inbound":{"callRelatedFields":["ANI","DNIS"],"objects":{"Contact":[{"displayName":"Name","apiName":"Name"},{"displayName":"Email","apiName":"Email"}],"Account":[{"displayName":"Account Name","apiName":"Name"},{"displayName":"Phone","apiName":"Phone"},{"displayName":"Fax","apiName":"Fax"}],"cnx__Phone__c":[{"displayName":"Phone Name","apiName":"Name"},{"displayName":"Phone Number Line 1","apiName":"cnx__Phone_Number_Line_1__c"},{"displayName":"Phone Number Line 2","apiName":"cnx__Phone_Number_Line_2__c"},{"displayName":"Type","apiName":"cnx__Type__c"},{"displayName":"Location","apiName":"cnx__Location__c"},{"displayName":"Call Manager","apiName":"cnx__Call_Manager__c"},{"displayName":"Mac Address","apiName":"cnx__Mac_Address__c"}]},"screenPopSettings":{"screenPopsOpenWithin":"ExistingWindow","SingleMatch":{"screenPopType":"PopToEntity"},"NoMatch":{"screenPopType":"DoNotPop"},"MultipleMatches":{"screenPopType":"DoNotPop"}}}}';
json = json.replace(/{/g, '[').replace(/}/g, ']').replace(/"\:/g, '#",');
json = JSON.parse(json);
document.write('<pre>' + JSON.stringify(json, 0, 4) + '</pre>');
#GregL is right the JSON parsed came in alphabetic or in case of a number in ascending order and to keep the order you'll need an incremented number logic like:
var position_in_array = 0
var name = 'screenPopSettings'
object[`${position_in_array}${name}`] = value
position_in_array += 1
The parseJson returns data in object form and object doesn't has index. So we should define custom index of data array, if we want to keep the array index.
Example:
$arr[0] = array(
'Contact'=>array(
'key1'=>'val',
)
);
$arr[1] = array(
'Account'=>array(
'key1'=>'val',
)
);
It will produce the output as per the array index originally defined before parseJson function call.

Keep the sort order

I have a object with that values :
category_list = {
"1000":{
"name":"Cars",
"order":"1",
"level": "2"
},
"2010":{
"name":"Houses",
"order":"2",
"level": "2"
},
"1030":{
"name":"Cars",
"order":"3",
"level": "2"
}
}
And when I would like to show it Chrome reorders it based on the Index :
It becomes :
category_list = {
"1000":{
"name":"Cars",
"order":"1",
"level": "2"
},
"1030":{
"name":"Cars",
"order":"3",
"level": "2"
},
"2010":{
"name":"Houses",
"order":"2",
"level": "2"
}
}
I wish to keep the order as it was when pushing! or reorder based on field "order"
Can someone please help with that?
JavaScript objects are by definition unordered.
If you need an ordered list, you should use an array (of objects) instead, e.g.:
var objs = [
{
"key": 1000,
"name":"Cars",
"order": 1,
"level": 2
}, ...
];
objs.sort(function(a, b) {
return a.order - b.order;
});
NB: for numeric properties use numeric types.
JavaScript objects do not guarantee a specific order for their attributes. So the structure you'd like to have simply doesn't exist in JavaScript.
So with the native structures you can get either:
Array: Guaranteed order, but only accessing elements sequentially or by a numeric (0..n-1) index
Object: Arbitrary order, but you can access elements sequentially (again, arbitrary order) or using its key (which can be any string)
If you need both you either need to add an array that maps the order to the object keys, e.g. [1000, 2010, 1030] or store the data in an array and create a mapping like this: {1000: 0, 2010: 1, 1030: 2}.

Can a JSON array contain objects of different key/value pairs?

Can a JSON array contain Objects of different key/value pairs. From this tutorial, the example given for JSON array consists of Objects of the same key/value pair:
{
"example": [
{
"firstName": "John",
"lastName": "Doe"
},
{
"firstName": "Anna",
"lastName": "Smith"
},
{
"firstName": "Peter",
"lastName": "Jones"
}
]
}
If I want to change it to have different key/value pairs inside the JSON array, is the following still a valid JSON?
{
"example": [
{
"firstName": "John",
"lastName": "Doe"
},
{
"fruit": "apple"
},
{
"length": 100,
"width": 60,
"height": 30
}
]
}
Just want to confirm this. If so, how can I use JavaScript to know if the JSON "example" field contains the first homogeneous objects or the second heterogeneous objects?
You can use any structure you like. JSON is not schema based in the way XML is often used and Javascript is not statically typed.
you can convert your JSON to a JS object using JSON.parse and then just test the existence of the property
var obj = JSON.parse(jsonString);
if(typeof obj.example[0].firstName != "undefined") {
//do something
}
It doesn't matter you can mix and match as much as you want.
You could just test it
typeof someItem.example !== 'undefined' // True if `example` is defined.
It's perfectly valid JSON. Personally I prefer this syntax better, because it reads easier:
{
"example": [
{
"firstName": "John",
"lastName": "Doe"
},
{
"fruit": "apple"
},
{
"length": 100,
"width": 60,
"height": 30
}
]
}
As to answer your second question, you can read data from a JSON string by using var data = JSON.parse(datastring);. Then simply use it by calling data.property.secondlevel. Any variable can be an object, array, string or number, allowing for nested structures.
You are free to do what you want with the contents of the array. Jus remember about this before you try to iterate an access properties of each item in your array.
one thing: you won't be able to deserialize this to anything else than an array of object in your server side, so don't have surprises later.
as a hint, maybe you could include a common field in the objects specifying the "type" so later is easy to process.
var array = [{"type":"fruit", "color":"red"},
{"type":"dog", "name":"Harry"}];
var parser = {
fruit:function(f){
console.log("fruit:" + f.color);
},
dog: function(d){
console.log("dog:"+d.name);
}};
for(var i=0;i<array.length;i++){
parser[array[i].type](array[i]);
}

Categories

Resources