I have the following JSON data being returned, but for some reason, Javascript or jQuery ajax seems to re-organise the items list. The server returns the data sorted alphabetically by item.title (verified)...
The JSON below is after the ordering has been butchered:
{
"count": 3,
"items": {
"tardis": {
"type": 40,
"title": "Tardis",
"timeMachine": true,
"reliable": true
},
"stargate": {
"type": "Milky way gate",
"title": "Stargate + solar flare",
"timeMachine": true,
"reliable": false
}
}
}
Does anyone why the ordering is being tampered with? How can I re-order the items byt the title value?
Your items object is not an array, but just an object with named members. These members have no inherent order.
For instance, doing a console.log({ your object }) in chrome will yield the properties sorted by the member name, in this case "stargate" and "tardis", in that order. But writing for(k in x.items) console.log(k) for the exact same object, will (in Chrome - again, no reliable specification here) iterate over the objects in the order they were defined, and log "tardis", "stargate".
This ordering is an artifact of how an object is presented, not of the object itself. Use arrays if you want ordering:
{
"count": 3,
"items": [
{
"key": "stargate",
"type": "Milky way gate",
"title": "Stargate + solar flare",
"timeMachine": true,
"reliable": false
},
{
"key": "tardis",
"type": 40,
"title": "Tardis",
"timeMachine": true,
"reliable": true
}
]
}
The keys of an object are not in a defined order. They can be returned in any order once they are put into a javascript object. This is as the language was designed and as specified.
If you want them in a specific order, then you either need the data to be in an array (which is ordered) or you need an ordered index for just the keys that will let you access the keys in a desired order.
Arrays have a consistent order, objects do not.
It looks to me like you may want a data structure that looks like this:
{
"count": 3,
"items": [
{
"name": "tardis",
"type": 40,
"title": "Tardis",
"timeMachine": true,
"reliable": true
},
"name": "stargate",
"type": "Milky way gate",
"title": "Stargate + solar flare",
"timeMachine": true,
"reliable": false
}
]
}
This way, the items are in an array with a specific order: items[0], items[1], etc...
FYI, when you do it this way, you don't need the "count" value because the items array will have items.length.
Without the count value, your whole response could just be the array of objects:
[
{
"name": "tardis",
"type": 40,
"title": "Tardis",
"timeMachine": true,
"reliable": true
},
"name": "stargate",
"type": "Milky way gate",
"title": "Stargate + solar flare",
"timeMachine": true,
"reliable": false
}
]
If you read the JSON specification at http://www.json.org/, You'll come across this line -
An object is an unordered set of name/value pairs
Hence its not wise to trust the ordering of keys in an object. Declare it as an array and you can have your order.
Related
I want to take items from this array (the way I save things on the client)
[
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
]
And turn them into this format for how I save it server side
{ "todos": {
"-Mdawqllf_-BaW63gMMM": {
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800,
},
"-Mdawqllf_-BaW63gGHf": {
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000,
},
"-Mdawqllf_-BaW63gGHd": {
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000,
}
},
}
Basically i turn items into an array on the client to help with sorting and making use of arrays. But before sending it back need to put into the right format
Use .map() to loop over the array of objects to exctract the id property, so you can use it as the key of the new object.
Use Object.fromEntries() to create the new object from the array returned by .map().
const data = [
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
];
const todos = {
Todos: Object.fromEntries(data.map(obj => [obj.id, obj]))
};
console.log(todos);
#Barmar's solutions is nice.
For the sake of learning or others googling. You can also reduce the array to an object.
const todos = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
const items = {
todos: {
...data
}
};
Assume that data is the array of objects.
Use the spread operator to copy all the array objects from data array to the todos object at key todos.
One important thing to note that you can't assign more than one objects without array to a single object key. You definately have to use the array to maintain all the objects under the one key.
Avoid using the hardcode index. Always use the spread operator
For a Chrome app, wich stores data in IndexedDB, i have a object like this:
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"parcels": [
{
"service": "DHL",
"track": "12345"
},
{
"service": "UPS",
"track": "3254231514"
}
]
}
If i store the hole object in an objectStore, can i use an index for "track", which can be contained multiple times in each order object?
Or is it needed or possibly better/faster to split each object into multiple objectStores like know from relational DBs:
order
orderitem
parcel
The solution should also work in a fast way with 100.000 or more objects stored.
Answering my own question: I have made some tests now. It looks like it is not possible to do this with that object in only 1 objectStore.
An other example object which would work:
var myObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"shipping": {"method": "letter",
"company": "Deutsche Post AG" }
}
Creating an index will be done by:
objectStore.createIndex(objectIndexName, objectKeypath, optionalObjectParameters);
With setting objectKeypath it is possible to address a value in the main object like "name":
objectStore.createIndex("name", "name", {unique: false});
It would also be possible to address a value form a subobject of an object like "shipping.method":
objectStore.createIndex("shipping", "shipping.method", {unique: false});
BUT it is not possible to address values like the ones of "track", which are contained in objects, stored in an array. Even something like "parcels[0].track" to get the first value as index does not work.
Anyhow, it would be possible to index all simple elements of an array (but not objects).
So the following more simple structure would allow to create an index entry for each parcelnumber in the array "trackingNumbers":
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"trackingNumbers": ["12345", "3254231514"]
}
when creating the index with multiEntry set to true:
objectStore.createIndex("tracking", "trackingNumbers", {unique: false, multiEntry: true});
Anyhow, the missing of the possibility to index object values in arrays, makes using indexedDB really unneeded complicated. It's a failure in design. This forces the developer to do things like in relational DBs, while lacking all the possibilities of SQL. Really bad :(
Can I create an object dynamically from JSON?
This is one of some in array:
values: [{
"$type": "Entrance, DataModel",
"EntranceDeviceData": {
"$type": "DeviceData, DataModel",
"Watchdog": 0,
"Inputs": {
"$type": "Int16[], mscorlib",
"$values": [0, 0]
},
"Outputs": {
"$type": "Int16[], mscorlib",
"$values": [0, 0]
},
"Faults": {
"$type": "Int16[], mscorlib",
"$values": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
"StandingCommand": 0
},
"Vehicle": null,
"NextStates": {
"$type": "System.Collections.Generic.List`1[[System.String, mscorlib]], mscorlib",
"$values": ["CarApproachingBarrier"]
},
"Repository": {
"$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"
},
"Direction": 0,
"Name": "Entrance",
"Position": "0,0,0,0",
}, {...another object...
}, {...another one...
}
]
This both JSON objects are different. Can I create an object (for every other JSON object) without knowing in advance it's properties? How can I do it?
(I heard something that it possible, but maybe I didn't understand well the person who said that).
What you gave as examples of JSON in your original code above is Javascript's way of defining literal objects. json1 and json2 already ARE javascript objects, no need to create them.
// original code from question
var json1 = {
"mysex": "female",
"yoursex": "male",
"location": {
"lat": "48",
"lng": "1"
},
"description": "descr2",
"owner": "zBYnfuu8DXEwMttwZ",
"nickname": "user",
"_id": "1"
};
As nnnnnn pointed out below JSON is most commonly used to refer to a STRING containing code formatted as above, that would be:
var json1_as_string = '{
"mysex": "female",
"yoursex": "male",
"location": {
"lat": "48",
"lng": "1"
},
"description": "descr2",
"owner": "zBYnfuu8DXEwMttwZ",
"nickname": "user",
"_id": "1"
}';
To get from such a String to an actual Javascript Object you would need to parse it:
var json1 = JSON.parse(json1_as_string);
the opposite direction (Javascript Object to String) is achieved by stringify:
var json1_as_string = JSON.stringify(json1);
see https://developer.mozilla.org/en-US/docs/Using_native_JSON
p.s.
It does seem strange that these two very different objects have the same "_id".
You've changed the question completely, and I'm trying to understand what you are asking.
This both JSON objects are different. Can I create an object (for
every other JSON object) without knowing in advance it's properties?
How can I do it?
Yes, in Javascript you can create objects without knowing their properties in advance. Javascript is not strongly typed, and it has no classes. So there's absolutely no problem
with having objects with different properties.
My JavaScript object looks like this:
"ivrItems": {
"50b5e7bec90a6f4e19000001": {
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
"50b5e7c3c90a6f4e19000002": {
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
},
"50b5e7c8c90a6f4e19000003": {
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
}
}
Now I want to change the order of the object dynamically.
After sorting, the object should look as follows:
"ivrItems": {
"50b5e7bec90a6f4e19000001": {
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
"50b5e7c8c90a6f4e19000003": {
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
}
"50b5e7c3c90a6f4e19000002": {
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
}
}
Is there any possible way to do this?
To get and then change the order of an Object's enumeration, you need to manually define the order. This is normally done by adding the properties of the object to an Array.
var keys = Object.keys(data.ivrItems);
Now you can iterate the keys Array, and use the keys to access members of your irvItems object.
keys.forEach(function(key) {
console.log(data.irvItems[key]);
});
Now the order will always be that of the order given by Object.keys, but there's no guarantee that the order will be what you want.
You can take that Array and reorder it using whatever ordering you need.
keys.sort(function(a, b) {
return +data.irvItems[a].key - +data.irvItems[b].key;
});
This sort will sort the keys by the nested key property of each object after numeric conversion.
You should use an Array. Object keys has no order
like this:
{
"ivrItems": [
{
"id": "50b5e7bec90a6f4e19000001",
"name": "sdf",
"key": "555",
"onSelect": "fsdfsdfsdf"
},
{
"id": "50b5e7c8c90a6f4e19000003",
"name": "dfdf",
"key": "55",
"onSelect": "dfdffffffffff",
"parentId": null
},
{
"id": "50b5e7c3c90a6f4e19000002",
"name": "dfgdf",
"key": "666",
"onSelect": "fdgdfgdf",
"parentId": null
}
]
}
You're probably going to have a tough time with cross-browser compatibility, if you're doing this in the browser. But computers are mostly deterministic, so you could probably accomplish this reliably in one javascript engine implementation, though. For example, in the Chrome REPL / console, you can get this order simply by sequencing adding the properties:
var n = {}
n.b = 2
n.c = 3
var m = {}
m.c = 3
m.b = 2
JSON.stringify(n)
> "{"b":2,"c":3}"
JSON.stringify(m)
> "{"c":3,"b":2}"
So you could reconstruct your object, adding the keys in the order you want to find them later.
But the other people are right, if you want true, predictable order, you should use an array.
Javascript objects are intrinsically unordered.
You can't do that.
I am getting a JSON in response from server:
{
"width": "765",
"height": "990",
"srcPath": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_MERGED_/1273.pdf",
"coverPage": "",
"documents": [
{
"index": "1",
"text": "Archiving Microsoft® Office SharePoint® Server 2007 Data with the Hitachi Content Archive Platform and Hitachi Data Discovery for Microsoft SharePoint",
"type": "doc",
"id": "HDS_054227~201106290029",
"children": [
{
"text": "Page 1",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_1.png"
},
{
"text": "Page 2",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_2.png"
}
]
},
{
"index": "11",
"text": "Brocade FCoE Enabling Server I/O Consolidation",
"type": "doc",
"id": "HDS_053732~201105261741",
"children": [
{
"text": "Page 1",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_053732~201105261741/image_1.png"
},
{
"text": "Page 2",
"leaf": "true",
"pageLocation": "http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_053732~201105261741/image_2.png"
}
]
}
]
}
And I want to get pagelocation of the children.
Can anyone tell me how to do this?
Hi
i also want to get indexes from this and then want to get pagelocations of that particular children. Can you tell me how would i do that?
And also when i when i am getting indexes array it is returning me ,, only and not the index nos.
I am using following code for that :
indexes=response.documents.map(function(e){ return e.children.index; })
Thanks & Regards
If you're interested in simply retrieving all the page locations, you can do it using filter:
var locations = [];
json.documents.forEach(function(e,i) {
e.children.forEach(function(e2,i2) {
locations.push(e2.pageLocation);
)}
});
// returns flat array like [item1,item2,item3,item4]
You can get an array of arrays using map:
var locations = [];
var locations = json.documents.map(function(e) {
return e.children.map(function(e2) {
return e2.pageLocation;
});
});
// returns 2-dimensional array like [[item1,item2],[item1,item2]]
Your json response is an appropriate javascript object So you can access all elements of the object like you do as in back end.
here, you have an array of object of the type documents and each document object has array of objects of the type children. so
syntax would be
myjson.documents[0].children[0].pagelocation
( = http://192.168.5.13:8888/ebook/user_content/_ADMIN_/_IMAGES_/HDS_054227~201106290029/image_1.png)
will give you the very first page location..
and so on