axios: stop automatic sorting of objects based on keys
Asked Answered
P

3

6

I am gettting an api response using axios.

I am sending the api response sorted w.r.t name http://localhost:8000/api/ingredients/ordering=name

The actual object sent is as below from my server.

{
    2:{"id":2,"name":"anil"},
    1:{"id":1,"name":"sant"},
    3:{"id":3,"name":"vino"}
}

or pass the key as string instead of integer

{
    "2":{"id":2,"name":"anil"},
    "1":{"id":1,"name":"sant"},
    "3":{"id":3,"name":"vino"}
}

or key as alphanumeric

{
    "a2":{"id":2,"name":"anil"},
    "a1":{"id":1,"name":"sant"},
    "a3":{"id":3,"name":"vino"}
}

what axios is doing is sorting the objects w.r.t keys and the names are not in sorted order

{
    1:{"id":1,"name":"sant"},
    2:{"id":2,"name":"anil"},
    3:{"id":3,"name":"vino"}
}

or if key is alpha numeric

{
    a1:{"id":1,"name":"sant"},
    a2:{"id":2,"name":"anil"},
    a3:{"id":3,"name":"vino"}
}

How to stop this

I dont want in array format the list because i have to update the individual objects later based on the id. This representation is easy. I am using reactjs state.

Pagurian answered 9/12, 2017 at 10:3 Comment(1)
JavaScript objects are not ordered.If you want objects in certain order, use array.Hindman
J
3

There is answer here Does JavaScript Guarantee Object Property Order? among other that says:

most browsers returns properties in the same order as they were inserted, but it was explicitly not guaranteed behaviour so shouldn't have been relied upon.

The ECMAScript specification used to say:

The mechanics and order of enumerating the properties ... is not specified.

However in ES2015 and later non-integer keys will be returned in insertion order.

So don't rely on order of an object keys. If you don't worry about ES5 you can try to use non-integer keys - strings for instance but note that strings like '1' are not suitable http://code.google.com/p/v8/issues/detail?id=164.

You can find on the page of the answer also:

If you rely on insertion order, you are outside the ECMAScript spec, but within the de-facto standard of common browser behavior as long as your keys don't parse as integers.

UPDATE

Short answer is axios doesn't sort keys of an object

https://jsfiddle.net/zabq841t/

axios.get('/echo/js/?js={a2: 1, a1: 0}')
    .then((res) => {
        //res.data is {a2: 1, a1: 0}
    })

You can get sorted version because of old browser or your server. Take a look fiddle if it works for you then probably you have 'issue' on server side. You need to provide more details about you server app.

Johnjohna answered 9/12, 2017 at 10:48 Comment(0)
M
1

This is an expected behavior for objects in JavaScript.

If you want to have the order intact, use Arrays, So your example would turn out like this,

const obj = [{name:"two"},{name:"three"},{name:"one"}];

If you need to pass keys, then reorder it in this way, enter image description here

Edited

Back to your edited version, say you want to update your object based on ID and this is your provided json,

{
    a1:{"id":1,"name":"sant"},
    a2:{"id":2,"name":"anil"},
    a3:{"id":3,"name":"vino"}
}

Nothing will stop you from doing so, if you want to change details for an object with id:2, you can do the following to get the key a2,

const key = Object.entries(obj).find(entry => entry[1].key === 2)[0];
const desiredElement = obj(key);

Breakdown of the code,

Object.entries(obj) // get entries from object
.find(entry) //where entry[0] is key, entry[1] is value/object
entry[1].id=== 2 // return the element that has id === 2
[0] // since entry[0] is key, then it would hold a2 here

Now we can use the key as we want like, Obj[key], and update it as well.

Mart answered 9/12, 2017 at 10:47 Comment(0)
W
0

Just use lodash cloneDeep and all set.

return axios.get(API_URL + apiEndpoint + payload, { headers: getHeaders(headers) })
.then((response) => {
  return _.cloneDeep(response)
})
Wingard answered 30/8 at 17:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.