Is it true that JSON.parse() sorts properties if the keys contain numeric values?

Many posts on this topic contain assertions that can be summarized like so:

  1. Object properties are never guaranteed to be ordered in any way.
  2. JSON.parse() never sorts properties in any specific way.

We typically have no doubts about #1 above, so it is expected that properties are processed in the order they appear.
[edit, following @Bergi's comment: or at least they should appear in a random order]

From this, we might infer that #2 should also hold true.

However, when looking at the provided snippet:
(Note: To display the results, snippets below do not use console.log() which may change the output order. Instead, objects are iterated using for (key in obj) and the output is displayed in the document.)

var inputs = [
  '{"c": "C", "a": "A", "b": "B"}',
  '{"3": "C", "1": "A", "2": "B"}',
  '{"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}'
];

for (var i in inputs) {
  var json = inputs[i],
      parsed = JSON.parse(json),
      output = [];
  for (var j in parsed) {
    output.push(j + ': ' + parsed[j]);
  }
  document.write(`JSON: ${json}<br />Parsed: ${output.join(', ')})<hr />`);
}

The snippet reveals that:

  • When input keys have non-numeric values, the parsed object retains the original order of properties from the input. This aligns with the assumption made in #2.
  • Conversely, when keys have numeric values (as strings), the parsed object has its properties sorted. This goes against the assumption made in #2.
  • Additionally, in cases where there are both numeric and non-numeric key values, the numeric properties appear first in sorted order followed by the non-numeric properties in their original order.

Initially, one might conclude that there is an undocumented feature where JSON.parse() follows the mentioned rules. However, further exploration shows how different objects are handled:

var objects = [
  [
    '{"c": "C", "a": "A", "b": "B"}',
    {"c": "C", "a": "A", "b": "B"}
  ],
  [
    '{"3": "C", "1": "A", "2": "B"}',
    {"3": "C", "1": "A", "2": "B"}
  ],
  [
    '{"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}',
    {"c": "C", "a": "A", "3": "C", "1": "A", "b": "B", "2": "B"}
  ]
];

for (var i in objects) {
  var object = objects[i],
      output = [];
  for (var j in object[1]) {
    output.push(j + ': ' + object[1][j]);
  }
  document.write(`Code: ${object[0]}<br />Object: ${output.join(', ')}<hr />`);
}

Similar observations are made where properties seem to follow a specific rule regardless of how they are coded:

  • Numerically named properties are all sorted and come first.
  • Other properties follow in the order they were coded.

This behavior seems to be inherent to the object building process rather than being attributed to JSON.parse(). It appears to be a fundamental aspect, albeit undocumented from what I could find.

Any insights into the definitive rules governing property order?


[Edit, thanks to @Oriol's answer] A synthetic explanation is as follows:

  • This behavior aligns with an ECMA specification rule.
  • While this rule should apply to methods where order is guaranteed, it is optional for other scenarios.
  • Modern browsers seem to uniformly apply this rule across all methods, leading to the observed contradictions.

Answer №1

An object's properties do not follow a specific order, making it impossible for JSON.parse to sort them. The enumeration of an object's properties may or may not have a defined order.

This is true for neither for...in loops nor Object.keys

As elaborated in Is there a consistent order for object property enumeration introduced by ES6?, the specification states

The process and sequence of enumerating properties are left unspecified

However, this is true for OrdinaryOwnPropertyKeys

Objects utilize an internal [[OwnPropertyKeys]] method, such as with Object.getOwnPropertyNames and Object.getOwnPropertySymbols.

In the case of standard objects, this method employs the OrdinaryGetOwnProperty abstract operation, which organizes properties in a specific order:

During execution of the OrdinaryOwnPropertyKeys abstract operation on Object O, the following steps occur:

  1. Create a new empty List named keys.
  2. For each unique integer index own property key P of O, in ascending numeric index order
    1. Append P to the end of keys.
  3. For each unique String type own property key P of O, ordered chronologically based on creation
    1. Append P to the end of keys.
  4. For each Symbol type own property key P of O, ordered chronologically based on creation
    1. Append P to the end of keys.
  5. Return keys.

Hence, due to the need for order in OrdinaryOwnPropertyKeys, some implementations may choose to store properties internally in that manner and apply it during enumeration. While this might be what you've noticed, it cannot be guaranteed.

Additionally, keep in mind non-standard objects (like proxy objects) may possess a separate [[OwnPropertyKeys]] internal method, so the order when using Object.getOwnPropertyNames could differ too.

Answer №2

It is conceivable that properties are processed in the order they appear for any given operation

However, there lies a flaw in this line of reasoning. Since object properties do not have a guaranteed order, it must be acknowledged that operations may process properties in any sequence they deem fit.

Engines have actually evolved to handle integer properties differently, treating them akin to array indices and storing them in a more efficient format than a traditional lookup table.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Babel had a SyntaxError in test.jsx file at line 3, position 11 with an Unexpected token

Having trouble converting JSX to JS with Babel? If you're seeing an error like the one below, don't worry - we can help you fix it: The example code in test.jsx is causing a SyntaxError when transformed using babel test.jsx: SyntaxError: test ...

Guide on transferring HTML tags via JSON with PHP!

A particular function is called with certain parameters, which then executes a query on the database and retrieves some data. However, the result returned by this function includes HTML elements and double quotes that need to be properly formatted for disp ...

Updating Json property names in c#

In my class, I have several fields that are used for serializing into a JSON object when making calls to an external REST API method. public class Customer { [JsonProperty(PropertyName = "email")] public string Email { get; set; } ...

Experiencing difficulties in transmitting multipart form data from React to Express Js accurately

I am facing an issue with uploading files using Dropzone and sending them to a Java backend API from React JS. In this scenario, React sends the document to Express backend where some keys are added before forwarding the final form data to the Java endpoin ...

Modeling JSON structures in Couchbase

I am eager to delve into working with Couchbase and its JSON-document oriented approach. However, I'm unsure about the most efficient way to store and structure data for later retrieval. Are there any tutorials available that can help me get started? ...

What is the best way to assign the result of a promise to a variable?

My code includes an async function that retrieves a value async fetchUserName(environment: string, itemName: string, authToken: string): Promise<any> { let result = await this.obtainDeviceName(environment, itemName, authToken); return ...

receive the output of the inquiry

Here's the issue I'm facing: file accounts.controlles.ts import { requestT } from "src/service/request.api"; export const getaccounts = async () => { const response = await requestT({ method: "GET", ur ...

Is it possible to retrieve data from this Map by querying only for values less than 5?

I am in possession of various documents that are housed within this particular collection. Document 1 https://i.sstatic.net/kbwl0.png Document 2 https://i.sstatic.net/YPObc.png Each document, contained within these collections, holds varied values for ...

Guide on extracting HTML content from JSON and displaying it in a UIWebView (utilizing Swift 3.0)

Can anyone guide me on how to use JSON2HTML to parse HTML data from JSON and display it in an UIWebView using Swift 3.0? Your help is much appreciated! This is what I have attempted so far: let jsfile1 = try!String(contentsOfFile: Bundle.main.path(forRes ...

Adjusting the position of the top left corner is causing issues with my X and Y coordinates

Utilizing a resize feature with KineticJS that has been customized to suit my requirements (source: ) One of the specific needs is for users to reset the position of their image to a predefined X and Y coordinate while ensuring it fits within the drawingB ...

Converting JSON data into HTML presentation

After uploading the image using AJAX and receiving a JSON response, I found the following data in my console: 0"C:\xampp\htdocs\3Dklik\..../1492427792slider_7.jpg" 1"C:\xampp\htdocs\3Dklik\mog/1492427792slider_2.jpg ...

What is the process for a server to transmit a JWT token to the browser?

Here is an example response sent to the browser: HTTP / 1.1 200 OK Content - Type: application / json Cache - Control : no - store Pragma : no - cache { "access_token":"MTQ0NjJkZmQ5OTM2NDE1Z ...

Having trouble getting Javascript to reveal hidden elements based on their class

I am having some trouble making specific fields in a form appear based on the selection made from a dropdown menu. Below is a simplified snippet of my code, which should change the display from 'none' to 'block'. Can you help me figure ...

Sending a Variable and List to a Controller using Ajax

I am having an issue with passing data from a Text Box and a Select Options Multiple using knockout selectedOptions in a viewModel to my Controller via ajax. I am unable to receive the MetricsChosenModel information. var MetricsChosenModel= wi ...

Employing a one-time use variable that is asynchronously loaded via a React hook

Currently, I am exploring the functionalities of React's hooks, but I'm encountering a roadblock when it comes to integrating different use cases. The main goal is to create a hook called useNationsAsync that fetches a list of available nations ...

Child component in VueJs is undergoing a situation where the variable is found to be

Whenever an event is triggered, a function is called to populate a variable and open a modal from a child component. However, in the modal, the new variable appears empty initially. If I close and then reopen the modal, the data finally loads. I have atte ...

Issue encountered: Component returning nothing error in a Next.js/React application

I'm currently working on creating image slider component using Nextjs/React and Emotion. I thought I had everything set up correctly but unfortunately, I keep encountering this common error... Error: ImageSliderContainer(...): Nothing was returned f ...

Is there a variation in IE6 versions depending on the operating system used?

It's puzzling to me that customers are reporting bugs on W2K machines in IE6, yet when I test locally on a WinXP System, everything appears normal. Could it be possible that there are differences in JavaScript Execution between the two systems? I do ...

Tips for setting up your Webpack configuration

I'm having trouble compiling sass and jade. Although I found an option for sass, it only compiles at startup and doesn't work properly. Here are the commands I've tried: webpack-dev-server --watch-poll webpack-dev-server --watch webpack ...

What is the process for creating text within a rectangle using canvas, pixi.js, or three.js?

I've been tasked with creating a dynamic progress bar that shows the time remaining until a specific date. While I've successfully implemented the countdown feature, I'm now faced with the challenge of making the numbers fill in a specified ...