I've read through both the RFC and JSON.org and couldn't see a reference to whether array indexes were 0-based or 1-based. Being originally 'discovered' in JS, does everyone just assume it is 0-based?
For example:
{
"selectedItem": 1,
"Items": ["boots", "gloves", "hat"]
}
Is the selected item "boots" or "gloves"?
If this is the case (assumed 0-based), isn't this assumption potentially troublesome, particular if JSON support is implemented in languages that by default use 1-based indexes?
I don't think array index is a concept covered by JSON at all. A JSON array is just an ordered set written in a particular fashion:
An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
And that's all there is to it. Indexing questions are left to the end-points, the first element could be index 0, 1, -10, or "pancakes" and it wouldn't make any difference at all to JSON as long as the indexes matched the order of the elements in the array.
Back to specifics. Whether "selectedItem": 1 refers to "boots" or "gloves" is up to the JSON producer.
No, and it doesn't need one. There's no such thing as an array index in JSON. That selectedItem field is a simple integer. If it holds some reference to the other field, that's in the application domain, not the data notation.
JSON provides no means for referencing an element of an array, so the base index number is irrelevant.
Related
I Have a use case, where I generate a hash of a JSON object created in java initially and insert the hash and JSON object into the Postgres table as String and jsonb respectively.
I need to validate the JSON object saved initially in regular intervals, During that I fetch the JSON object from Postgres which is stored in jsonb and generate a hash out of it and compare it with the hash generated initially. Both are different now.
The reason is initially when data was inserted order of parameters was different in JSON Object at retrieval the order is different. Ending up generating 2 different hash for the same data.
Please suggest.
Use json type instead of jsonb per JSON:
Because the json type stores an exact copy of the input text, it will preserve semantically-insignificant white space between tokens, as well as the order of keys within JSON objects. Also, if a JSON object within the value contains the same key more than once, all the key/value pairs are kept. (The processing functions consider the last value as the operative one.) By contrast, jsonb does not preserve white space, does not preserve the order of object keys, and does not keep duplicate object keys. If duplicate keys are specified in the input, only the last value is kept.
The json data structure for jstree is define in https://github.com/vakata/jstree, here is an example
[ { "text" : "Root node", "children" : [ "Child node 1", "Child node 2" ] } ]
Notably it says
The children key can be used to add children to the branch, it should
be an array
However later on in section Populating the tree using AJAX and lazy loading nodes it shows to use set children to false to indicate when a child has not be processed
[{
"id":1,"text":"Root node","children":[
{"id":2,"text":"Child node 1","children":true},
{"id":3,"text":"Child node 2"}
]
}]
So here we see children used as both as an array and as a boolean
I am using jstree as an example because this is where I encountered the issue, but my question is really a general json question. My question is this, is it valid JSON for the same element in json to be two different types (an array and a boolean)
Structure wise, both are valid JSON packets. This is okay, as JSON is somewhat less stricter than XML(with a XSD or a DTD). As per: https://www.w3schools.com/js/js_json_objects.asp,
JSON objects are surrounded by curly braces {}.
JSON objects are written in key/value pairs.
Keys must be strings, and values must be a valid JSON data type (string, number, object, array, boolean or null).
Keys and values are separated by a colon.
Each key/value pair is separated by a comma.
Having said that, if the sender is allowed to send such JSONs, only caveat is that server side will have to handle this discrepancy upon receiving such different packets. This is a bad-looking-contract, and hence server might need to do extra work to manage it. Server side handling of such incoming JSON packets can become tricky.
See: How do I create JSON data structure when element can be different types in for use by
You could validate whether a JSON is okay or not at https://jsonlint.com/
See more about JSON in this answer: https://stackoverflow.com/a/4862511/945214
It is valid Json. JSON RFC 8259 defines a general syntax but it contains nothing that would allow a tool to identify that two equally named entries are meant to describe the same conceptual thing.
The need to have a criteria to check two JSON structures for instance equality has been one motivation to create something like Json Schema.
I also think it is not too unusual for javascript to provide this kind of mixed data. Sometimes it might help to explicitly convert the javascript object to JSON. Like in JSON.stringify(testObject)
A thing for json validation
https://www.npmjs.com/package/json-validation
https://davidwalsh.name/json-validation.
Is this valid JSON?
{
"a" : [
"x",
"x"
]
}
http://jsonlint.com/ says yes.
http://www.json.org/ doesn't say anything about it being forbidden, but does say:
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
"An ordered list of values" suggests duplicates are therefore valid. Is this correct? Is there anything more explicit? Are there any JSON implementation which don't allow duplicate values?
(Here's the related question about duplicate keys.)
That is valid JSON. What is not allowed is having duplicate keys, such as:
{
"a": 1,
"a": 2
}
Also, by "ordered" I believe it refers to the fact that values have a predefined, well established order, not that they are sorted in any way :)
Is there a way to serialize an empty array attribute (not null) of a struct and deserialize it back to an empty array (not null again)?
Considering that an empty array is actually a pointer to null, is the perceptible initial difference between an empty array and pointer to null completely lost after serialize/deserialize?
The worst practical scenario is that when I show an empty array attribute to my REST client, as a json "att":[], at first time, and, after cache register to redis and recover it, the same attribute is shown to my client as "att":null, causing a contract broken and a lot of confusing.
Summing up: is possible to show the Customer 2 addresses like an json empty array, after serialize/deserialize => https://play.golang.org/p/TVwvTWDyHZ
I am pretty sure the easiest way you can do it is to change your line
var cust1_recovered Customer
to
cust1_recovered := Customer{Addresses: []Address{}}
Unless I am reading your question incorrectly, I believe this is your desired output:
ORIGINAL Customer 2 {
"Name": "Customer number 2",
"Addresses": []
}
RECOVERED Customer 2 {
"Name": "Customer number 2",
"Addresses": []
}
Here is a playground to verify with: https://play.golang.org/p/T9K1VSTAM0
The limitation here, as #mike pointed out, is if Addresses is truly nil before you encode, once you decode you do not get the json equivalent null, but would instead end up with an empty list.
No, it's not possible. To understand why, let's look at the Go spec. For it to output two different results for empty vs. nil, any serialization method would need to be able to tell the difference between the two. However, according to the Go spec,
Two array types are identical if they have identical element types and
the same array length.
Since neither contains any elements and have the same element type, the only difference could be in length, but it also states that
The length of a nil slice, map or channel is 0
So through comparison, it would be unable to tell. Of course, there are methods other than comparison, so to really put the nail in the coffin, here's the portion that shows they have the same underlying representation. The spec also guarantees that
A struct or array type has size zero if it contains no fields (or
elements, respectively) that have a size greater than zero.
so the actual allocated structure of a zero length array has to be of size zero. If it's of size zero, it can't store any information about whether it's empty or nil, so the object itself can't know either. In short, there is no difference between a nil array and a zero length array.
The "perceptible initial difference between an empty array and pointer to null" is not lost during serialization/deserialization, it's lost from the moment initial assignment is complete.
For another solution, we have forked encoding/json to add a new method called MarshalSafeCollections(). This method will marshal Slices/Arrays/Maps as their respective empty values ([]/{}). Since most of our instantiation happens on the data layer we did not want to add code that fixed issues in our http response layer. The changes to the library are minimal and follow go releases.
I have a little dilema. I have a backend/Frontend Application that comunicates with a JSON based REST Api.
The backend is written in PHP(Symfony/jmsserializer) and the Frontend in Dart
The communication between these two has a little Problem.
For most List Data the backend responds with a JSON like
[{"id":1,...},{"id:2,....}]
But for some it responds with
{"0":{"id":1,...}, "1":{"id:2,....}}
Now my Question is should the backend respond with the later at all or only with the first?
Problem
You usually have a list of objects. You sometimes get an object with sub-objects as properties.
Underlying issue
JS/JSON-Lists are ordered from 0 upwards which means that if you have PHP-Array which does not respect this rule json_encode will output a JS/JSON-Object instead using the numeric indices as keys.
PHP-Arrays are ordered maps which have more features that the JSON-Lists. Whenever you're using those extra features you won't be able to translate directly into JSON-Lists without loosing some information (ordering, keys, skipped indices, etc.).
PHP-Arrays and JSON-Objects on the other hand are more ore less equivalent in terms of features and can be correctly translated between each other without any loss of information.
Occurence
This happens if you have an initial PHP-Array of values which respects the JS/JSON-List rules but the keys in the list of objects are modified somehow. For example if you have a custom indexing order {"3":{}, "0":{}, "1":{}, "2":{}} or if you have (any) keys that are strings (ie. not numeric).
This always happens if you want to use the numeric id of the object as the numeric index of the list {"123":{"id": 123, "name": "obj"}} even if the numeric ids are in ascending order... so long as they are not starting from 0 upwards it's not a json-list it's a json-object.
Specific case
So my guess is that the PHP code in the backend is doing something like fetching a list of objects but its modifying something about it like inserting them by (string) keys into the array, inserting them in a specific order, removing some of them.
Resolution
The backend can easily fix this by using array_values($listOfObjects) before using json_encode which will reindex the entire list by numeric indices of ascending value.
Arrays and dictionaries are two separate types in JSON ("array" and "object" respectively), but PHP combines this functionality in a single array type.
PHP's json_encode deals with this as follows: an array that only contains numeric keys ($array = ['cat', 'dog']) is serialized as JSON array, an associative array that contains non-numeric keys ($array = ['cat' => 'meow', 'dog' => 'woof']) is serialized as JSON object, including the array's keys in the output.
If you end up with an associative array in PHP, but want to serialize it as a plain array in JSON, just use this to convert it to a numerical array before JSON encoding it: $array = array_values($array);