You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JsonObject should support property order manipulation #102932
The JsonObject class implements IDictionary<string, JsonNode?>, however as of today the type does permit any manipulation of the order of its properties (even though order is being tracked internally). While this is consistent with the semantics of JSON where order of properties is not significant, it is often the case that one wants to arrange the order out of human readability concerns. For example, it is common for JSON schema docs to place the $schema and $id properties at the start of the object.
We should update JsonObject so that properties can be inserted at specific locations.
API Proposal
namespace System.Text.Json.Nodes;
public sealed partial class JsonObject : IDictionary<string, JsonNode?>
{
+ public int IndexOf(string key, out JsonNode? value);+ public void Insert(int index, string key, JsonNode? value);+ public void RemoveAt(int index);
}
API Usage
// Adds or moves the $id property to the start of the object
JsonObject schema = ...;
switch (schema.IndexOf("$id", out JsonNode? idValue))
{
case < 0: // $id property missing
idValue = (JsonNode)"https://example.com/schema";
schema.Insert(0, "$id", idValue);
break;
case 0: // $id property already at the start of the object
break;
case int index: // $id exists but not at the start of the object
schema.RemoveAt(index);
schema.Insert(0, "$id", idValue);
}
Alternative Designs
We can't have JsonObject implement IList<KeyValuePair<string, JsonNode?> (at least not without explicit implementation) since the base JsonNode class already exposes an indexer for ints with different signature and semantics.
For me, it is a serialization concern not a JSON Object model concern.
In some ways it is a thin-end-of-the-wedge problem; as soon as we start to suggest that JSON objects have a notion of "property ordering" outside of the serialized representation, people will start depending on it.
We already see subtle bugs from people depending on the fact that Dictionary<K,V> has remarkably stable ordering and I worry that this enters the same realm.
Unlike Dictionary, the JsonOject implementation uses a well-defined notion of property ordering. This proposal is simply a matter of making this available to users, should they have need for it.
So JsonObject isn't a model of a JSON object, it is intrinsically a model of a serialized representation of a JSON object. This lack of separation of concerns is where my discomfort lies.
I would have less discomfort if that was front-and-centre - i.e. this is not a JsonObject it is really a SerializedJsonObject.
(And the fact it is sometimes not-yet-serialized is a laziness optimization 😀)
So JsonObject isn't a model of a JSON object, it is intrinsically a model of a serialized representation of a JSON object. This lack of separation of concerns is where my discomfort lies.
Every model of a JSON object necessarily encapsulates a notion of property ordering, whether intentional or incidental. I wouldn't consider that a departure from the spirit of the JSON specification though; it is not that objects should not be orderable but rather that different permutations of the same object must be semantically equivalent. The latter should still be the case (cf. the implementation of the DeepEquals method etc).
This is true. And also true of e.g. dictionary enumeration. But we are careful to conceptually separate "regular dictionary" and "ordered dictionary" in the type system.
The conceptual change with this API is that we are transitioning from the former to the latter.
Just for clarity - I'm not wholly opposed, just "uncomfortable".
We should also implement IList<KeyValuePair<string, JsonNode?>>
Based on the discussion, wouldn't it be clearer to say: "We should also explicitly implement IList<KeyValuePair<string, JsonNode?>>" to make it clear that it's not public API
These APIs reflect the API surface in the newly added OrderedDictionary and solve a use case that would otherwise require making an explicit cast of the object to an IList instance.
Activity
dotnet-policy-service commentedon May 31, 2024
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.
gregsdennis commentedon May 31, 2024
This is good in order to support serialization scenarios.
Note that JSON Schema is set up to process these keywords first, regardless of where they appear in a document.
mwadams commentedon May 31, 2024
I feel this is the wrong place to support this.
For me, it is a serialization concern not a JSON Object model concern.
In some ways it is a thin-end-of-the-wedge problem; as soon as we start to suggest that JSON objects have a notion of "property ordering" outside of the serialized representation, people will start depending on it.
We already see subtle bugs from people depending on the fact that
Dictionary<K,V>has remarkably stable ordering and I worry that this enters the same realm.eiriktsarpalis commentedon May 31, 2024
Unlike Dictionary, the
JsonOjectimplementation uses a well-defined notion of property ordering. This proposal is simply a matter of making this available to users, should they have need for it.mwadams commentedon Jun 1, 2024
So
JsonObjectisn't a model of a JSON object, it is intrinsically a model of a serialized representation of a JSON object. This lack of separation of concerns is where my discomfort lies.I would have less discomfort if that was front-and-centre - i.e. this is not a
JsonObjectit is really aSerializedJsonObject.(And the fact it is sometimes not-yet-serialized is a laziness optimization 😀)
eiriktsarpalis commentedon Jun 1, 2024
Every model of a JSON object necessarily encapsulates a notion of property ordering, whether intentional or incidental. I wouldn't consider that a departure from the spirit of the JSON specification though; it is not that objects should not be orderable but rather that different permutations of the same object must be semantically equivalent. The latter should still be the case (cf. the implementation of the
DeepEqualsmethod etc).mwadams commentedon Jun 1, 2024
This is true. And also true of e.g. dictionary enumeration. But we are careful to conceptually separate "regular dictionary" and "ordered dictionary" in the type system.
The conceptual change with this API is that we are transitioning from the former to the latter.
Just for clarity - I'm not wholly opposed, just "uncomfortable".
eiriktsarpalis commentedon Jun 1, 2024
Like I said, unlike Dictionary JsonObject guarantees order of enumeration. It is very much implemented as an ordered dictionary.
terrajobst commentedon Jun 11, 2024
Video
int-based indexer onJsonNodework to return theJsonNodeoutthe property fromIndexOfthenIList<KeyValuePair<string, JsonNode?>>KennethHoff commentedon Jun 12, 2024
Based on the discussion, wouldn't it be clearer to say: "We should also explicitly implement
IList<KeyValuePair<string, JsonNode?>>" to make it clear that it's not public APIeiriktsarpalis commentedon Jun 18, 2024
In addition to the APIs as approved #102932 (comment) I propose the inclusion of the following methods:
These APIs reflect the API surface in the newly added OrderedDictionary and solve a use case that would otherwise require making an explicit cast of the object to an
IListinstance.