I am doing some processing with Groovy/Grails and the results are a map of type <String, Float>.
When returning the JSON object to the calling function (in this case, it's a flot diagram which requires [number,number] format), the key needs to be a number. This, in theory, is fine as my key to the map is a number in string form. I can't, however, figure out a way to create the JSON object with a numerical key.
I get results like this:
{"1":-9.814244910221474,"2":-9.710478606504552,"3":-9.636841089398253,"4":-9.524104819110796,"5":-9.522597036735684 ...}
instead of:
{1:-9.814244910221474,2:-9.710478606504552,3:-9.636841089398253,4:-9.524104819110796,5:-9.522597036735684 ...}
Does anyone know a way to force the JSON Map.encodeAsJSON() to produce an integer key? I've tried explicitly creating a map of type < integer,integer > before encoding it, and that doesn't work either.
Mike, Im looking at the json spec -- it appears that the keys must be strings. You should handle this client side.
http://www.json.org/
Related
I need to upload through a GraphQL mutation an object whose schema is not known at design time. Basically it is a raw JSON blob that may or may not come from other, possibly non-GraphQL services. I am using JSON scalar from https://github.com/graphql-java/graphql-java-extended-scalars:
scalar JSON
input MyInput {
jsonField: JSON
}
It works nicely except when the input blob contains keys like "$ref", which is the standard way to describe references in JSON. However, field name $ref does not seem to be accepted as it does not conform to the GraphQL naming conventions.
Obvious solutions appear to be to encode-decode field names in some way, or send the whole JSON as a String, perhaps with a custom scalar type. But is there perhaps a more elegant way to achieve this?
We receive a JSON object from network along with a hash value of the object. In order to verify the hash we need to turn that JSON into a string and then make a hash out of it while preserving the order of the elements in the way they are in the JSON.
Say we have:
[
{"site1":
{"url":"https://this.is.site.com/",
"logoutURL":"",
"loadStart":[],
"loadStop":[{"someMore":"smthelse"}],
"there's_more": ... }
},
{"site2":
....
}
]
The Android app is able to get same hash value, and while debugging it we fed same simple string into both algorithms and were able to get out same hash out of it.
The difference that is there happens because of the fact that dictionaries are unordered structure.
While debugging we see that just before feeding a string into a hash algorithm, the string looks like the original JSON, just without the indentations, which means it preserves the order of items in it (on Android that is):
[{"site1":{"url":"https://this.is.site.com/", ...
While doing this with many approaches by now I'm not able to achieve the same: string that I get is different in order and therefore results in a different hash. Is there a way to achieve this?
UPDATE
It appears the problem is slightly different - thanks to #Rob Napier's answer below: I need a hash of only a part of incoming string (that has JSON in it), which means for getting that part I need to first parse it into JSON or struct, and after that - while getting the string value of it - the order of items is lost.
Using JSONSerialization and JSONDecoder (which uses JSONSerialization), it's not possible to reproduce the input data. But this isn't needed. What you're receiving is a string in the first place (as an NSData). Just don't get rid of it. You can parse the data into JSON without throwing away the data.
It is possible to create JSON parsers from scratch in Swift that maintain round-trip support (I have a sketch of such a thing at RNJSON). JSON isn't really that hard to parse. But what you're describing is a hash of "the thing you received." Not a hash of "the re-serialized JSON."
I am building a REST API which creates a resource. The resource has only one attribute which is a rather long and unique string. I am planning to send this data to the API as JSON. I see two choices for modeling the data as JSON
A primitive JSON String data type
A JSON object with one String attribute.
Both the options work.
Which of these two options is preferred for this context? And why?
Basic Answer for Returning
I would personally use option 2, which is: `A JSON object with one String attribute.'
Also, in terms of design: I prefer to return an object, that has a key/value. The key is also a name that provides context as to what has been returned.
Returning just a string, basically a "" or {""} lacks that context ( the name of the returned variable.
Debate: Are primitive Strings Json Objects?
There seems to be also some confusion as to if a String by itself is a valid JSON document.
This confusion and debate, are quite evident in the following posts where various technical specs are mentioned: Is a primitive type considered JSON?
The only thing for sure is that a JSON object with a key-value pair is definitely valid!
As to a string by itself.. I'm not sure ( requires more reading).
Update: Answer In terms of creating/updating an entity (Post/Put)
In the specific case above, relating to such a large string that "runs into a few kilobytes"... my feeling is that this would be included within the request body.
In the specific context of sending data, I would actually be comfortable with using either 1 or 2. Additionally, 1 seems more optimized ( if your frameworks support it), since the context about what the data is, is related to the rest API method.
However, if in the future you need to add one more parameter, you will have to use a JSON entity with more than one key.
I'm using JsonCpp v0.6.0 to parse the following JSON string:
{
"3.7":"de305d54-75b4-431b-adb2-eb6b9e546011",
"3.7":"de305d54-75b4-431b-adb2-eb6b9e546012",
"3.8":"de305d54-75b4-431b-adb2-eb6b9e546013"
}
as follows:
Json::Value root;
Json::Reader reader;
// value contains the JSON string
if (!reader.parse(value, root, false))
{
// parse error
}
After the call to parse, root contains two entries in a map:
[0] first = "3.7", second = "de305d54-75b4-431b-adb2-eb6b9e546012",
[1] first = "3.8", second = "de305d54-75b4-431b-adb2-eb6b9e546013",
i.e. the first JSON record has been overwritten by the second. No errors are reported.
Is this behaviour expected? Is it correct?
I thought that an error might have been reported indicating that there is a duplicate key in the JSON string.
Like the JSON RFC sad the object names (keys) should be unique.
The names within an object SHOULD be unique.
Also the RFC defines if they are not, the behavior is unpredictable.
See this quote from the RFC:
An object whose names are all unique is interoperable in the sense
that all software implementations receiving that object will agree on
the name-value mappings. When the names within an object are not
unique, the behavior of software that receives such an object is
unpredictable. Many implementations report the last name/value pair
only. Other implementations report an error or fail to parse the
object, and some implementations report all of the name/value pairs,
including duplicates.
I agree with what you say, but I think JsonCpp tries to be a helpful tool, not something that tries to scrape by with minimal conformance to the RFCs.
It would make more sense if it either maintained the structure of the input stream, and supported duplicate keys, or (and this is what the OP and I'd expect) if it doesn't like it, to flag an error.
Silently changing the structure is unhelpful, as a check for the validity of the JSON input would have to be made with some other JSON tool prior to sending it to JsonCpp.
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);