loadJSON() changes order of JSON entries

Hello,

I just discovered Scriptable and I’m loving it, thank you!

I made a scripted based on the macstories example. When I select a dictionary inside an array it changes the order of the entries.
The following code should recreate my issue:

let url = "https://macstories.net/feed/json"
let req = new Request(url)
let json = await req.loadJSON()
console.log(json["items"][0])

In the original JSON the order is: “id”, “url”, “title”, “content_html” …
but using loadJSON() the order is: “author”, “id”, “content_html”, “title”…

For my use the order is important because I have one event per entry in chronological order.

Thanks in advance,
Régis

Technically the object order is not necessarily maintained, but where a parser can maintain it, it can be useful. But for transportability, you would ideally design in any sorting you require.

As an aside, here’s a good article that talks about the topic and provides good supporting arguments for the retention of ordering.

Whilst I’m all for defensive and transportable coding, it is of course a very useful feature to have if the code is only ever being run in the one place. Simplicity is always a winner.

1 Like

as long as the “items” order is not being changed, how does that matter? When you are looping the items. items[0].id is always going to be items[0].id no?

So the OP wants to loop through the key/value pairs.

I believe the design point is to use the key in a “direct access” way, rather than sequentially.

Or did I misunderstand?

That is what I had to realise the hard way. Thanks for the article.

The problem is that I don’t necessarily know the keys, in my case they are random dates:

[
 {
   "Category": "Store open",
   "2018-08-26": "false",
   "2018-09-07": "false",
   "2018-09-23": "false",
   "2018-10-21": "true",
   "2018-11-04": "true",
   "2018-11-18": "false",
   "2018-12-02": "true",
   "2018-12-16": "false",
   "2019-01-20": "false",
   "2019-02-03": "true",
   "2019-02-17": "false"
 },
 {
   "Category": "In charge",
   "2018-08-26": "Orcas",
   "2018-09-07": "WaWaLa.18",
   "2018-09-23": "Tiger",
   "2018-10-21": "Polarwölfe",
   "2018-11-04": "Erdmännchen",
   "2018-11-18": "Seelöwen",
   "2018-12-02": "Geckos",
   "2018-12-16": "?",
   "2019-01-20": "Eisbahn",
   "2019-02-03": "Seeadler",
   "2019-02-17": "Scouts"
 }
]

The easiest solution I can think of, is to change my json structure.

You can loop thru the keys in an Json object

const keys = Object.keys(someJsonObject)
for (const key of keys) {
  console.log(“key”, key);
   console.log(“value”, someJsonObject[key]);
}

In your previous example your json object is an array of objects then you will need to first loop through the array elements

for (const item of arrayObject) {
  const keys = Object.keys(item)
  for (const key of keys) {
    console.log(“key”, key);
     console.log(“value”, someJsonObject[key]);
  }
}
1 Like

I believe you can embed arrays in JSON. That might be order preserving.

Yes - it is stated in the RFC 7159 (JSON) specification that arrays are considered ordered.

It comes down to JSON Objects in Javascript are not ordered lists like Array are. The way you get data out of a JSON object is based on a key name, not a position index like Arrays.

–Scott.

1 Like

It also occurred to me that the keys could be “tree-like” with the top level key being a year.

Doesn’t solve the underlying issue but might be a better organisation. Something for the OP to consider.