I'm using the JSON-FRAMEWORK in objective C to parse a JSON object.
When I call [jsonString JSONValue], I get back a dictionary, but the keys aren't in the same order as the JSON Object I'm parsing. Is there anyway to keep this order the same?
In JSON objects, by definition, the order of the key-value pairs is not meaningful. The specification allows a JSON producer to permute them any way it want, even at random -- and does not require a parser to preserve the ordering. RFC 4627 says:
An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.
If you need the ordering to be preserved, what you have is not JSON, but a home-defined format that just happens to look superficially like JSON.
Related
I have a library that sends me results that include tuples. I need to process some of the data, serialize it and then it goes on its way to another system.
the tuples are ALWAYS made of 2 values but they are extremely wasteful when serialized:
(3, 4)
will serialize as:
{"Item1":3,"Item2":4}
whereas
[3; 4]
will serialize as:
[3,4]
I would like to avoid rebuilding the whole data structure and copying all the data to change this part.
Is there a way, at the serializer level, to convert the tuples into list?
the next process' parser can be easily changed to accommodate a list instead of tuples, so it seems like the best scenario.
the ugly option would be to fix the serialized string with a regex, but I would really like to avoid doing this.
You can override the default serialization behaviour by specifying your own JsonConverter. The following example shows a formatter that writes int * int tuples as two-element JSON arrays.
open Newtonsoft.Json
type IntIntConverter() =
inherit JsonConverter<int * int>()
override x.WriteJson(writer:JsonWriter, (a:int,b:int), serializer:JsonSerializer) =
writer.WriteStartArray()
writer.WriteValue(a)
writer.WriteValue(b)
writer.WriteEndArray()
override x.ReadJson(reader, objectType, existingValue, hasExistingValue, serializer) =
(0, 0)
let sample = [ (1,2); (3,4) ]
let json = JsonConvert.SerializeObject(sample, Formatting.None, IntIntConverter())
The result of running this will be [[1,2],[3,4]]. Note that I have not implemented the ReadJson method, so you cannot yet parse the tuples. This will involve some extra work, but you can look at existing JsonConverters to see how this should be done.
Also note that this is for a specific tuple type containing two integers. If you need to support other tuples, you will probably need to provide several variants of the converter.
I have an iterable of People that I save as a string after converting from json. I want to know how would I convert the string back to a list.
// Save data
val peopleString = myList.toString()
// String saved is
[People(name=john, age=23), People(name=mary, age=21), People(name=george, age=11)]
Now is it possible to convert peopleString back to a list?
val peopleList: List<People> = peopleString.?
In short, no... kind of.
Your output is not JSON, and toString() is the wrong function to use if you wanted JSON. The output of toString() is not a proper serialization format that can be understood and used to rebuild the original data structure.
Converting a data structure into some format so that it can be transmitted and later rebuilt is known as serialization. Kotlin has a serializer which can serialize objects into a number of different formats, including JSON: https://github.com/Kotlin/kotlinx.serialization#quick-example.
It's not as easy to use as toString(), but that's to be expected as toStrings's purpose is very different from serialization.
I need to serialize a (possibly complex *) object so that I can calculate the object's MAC**.
If your messages are strings you can simply do tag := MAC(key, string) and with very high probability if s1 != s2 then MAC(key, s1) != MAC(key, s2), moreover it is computationally hard to find s1,s2 such that MAC(k,s1) == MAC(k,s2).
Now my question is, what happens if instead of strings you need do MAC a very complex object that can contain arrays of objects and nested objects:
JSON
Initially I though that just using JSON serialization could do the trick but it turns out that JSON serializers do not care about order so for example: {b:2,a:1} can be serialized to both {"b":2,"a":1} or {"a":2,"b":1}.
URL Params
You can convert the object to a list of url query params after sorting the keys, so for example {c:1,b:2} can be serialized to b=2&c=1. The problem is that as the object gets more complex the serialization becomes difficult to understand. Example: {c:1, b:{d:2}}
1. First we serialize the nested object:{c:1, b:{d=2}}
2. Then url encode the = sign: {c:1, b:{d%3D2}}
3. Final serialization is: b=d%3D2&c=1
As you can see, the serialization quickly becomes unreadable and though I have not proved it yet I also have the feeling that it is not very secure (i.e. it is possible to find two messages that MAC to the same value)
Can anyone show me a good secure*** algorithm for serializing objects?
[*]: The object can have nested objects and nested arrays of objects. No circular references allowed. Example:
{a:'a', b:'b', c:{d:{e:{f:[1,2,3,4,5]}}, g:[{h:'h'},{i:'i'}]}}
[**]: This MAC will then be sent over the wire. I cannot know what languages/frameworks are supported by the servers so language specific solutions like Java Object Serialization are not possible.
[***]: Secure in this context means that given messages a,b: serialize(a) = serialize(b) implies that a = b
EDIT: I just found out about the SignedObject through this link. Is there a language agnostic equivalent?
What you are looking for is a canonical representation, either for the data storage itself, or for pre-processing before applying the MAC algorithm. One rather known format is the canonicalization used for XML-signature. It seems like the draft 2.0 version of XML signature is also including HMAC. Be warned that creating a secure verification of XML signatures is fraught with dangers - don't let yourself be tricked into trusting the signed document itself.
As for JSON, there seems to be a canonical JSON draft, but I cannot see the status of it or if there are any compliant implementations. Here is a Q/A where the same issue comes up (for hashing instead of a MAC). So there does not seem to be a fully standardized way of doing it.
In binary there's ASN.1 DER encoding, but you may not want to go into that as it is highly complex.
Of course you can always define your own binary or textual representation, as long as there is one representation for data sets that are semantically identical. In the case of an textual representation, you will still need to define a specific character encoding (UTF-8 is recommended) to convert the representation to bytes, as HMAC takes binary input only.
After overviewing the AMF0 specification I find that I cannot understand the proper way to encode the StrictArray type.
Here is the most immediate section of the specification:
array-count = U32
strict-array-type = array-count *(value-type)
which describes the StrictArray type with Augmented Backus-Naur Form (ABNF) syntax (See RFC2234)
Does the StrictArray type have ordinal indices or simply encoded objects (without ordinal keys) in order of their appearance in the StrictArray object graph?
Also, as an additional question, does the serialization table (from which object reference IDs are generated) contain all objects in the object graph, or only objects which can be potentially encoded via reference (ECMAArray,StrictArray,TypedObject,AnonymousObject)?
See https://github.com/silexlabs/amfphp-2.0/blob/master/Amfphp/Core/Amf/Serializer.php line 329 to 336.
you write the number of objects, then each object.
additional question: same code, look for Amf0StoredObjects.
references ids are only for referencable objects. These vary for AMF0 and AMF3 though.
I know returning types in a wcv service is allowed, and it will convert the object to json. But what if I don't want to return a random type, but return a string with formatted json? I can construct json my self but it can a) be messy, and b) not auto encode html values.
How do I do build a custom formatted json string? Off the top of my had, can I return a dictionary with key, value pairs? Will the value be encoded so you can transmitted without running the risk of malformed json?
Have a look at JSON.Net. I've used it in the past for serializing/deserializing to/from Json. It also (according to the web page) has support for converting Json to/from XML, so it seems reasonable that there would be some functions in there to build arbitrary Json strings in a way that is less error-prone than doing it yourself.
You can specify a return type of object and then use an anonymous type to return an arbitrary object. If you want to return an arbitrary collection, you can return IEnumerable, and use that to return a collection of anonymous types.
as far as I can understand, you want a webservice that returns a string that can be parsed using json (like JSON.parse(yourReturnedString)... As ckramer answered, JSON.NET can help to format your whatever dictionary into json but you should know dictionary is "json-serialised" as key:'your key', value:'your value§that can be also an object that will be serialized', so if you are using JSON.NET, you should also once it has been deserialezed, remove all the "key": and ,"value" JSON.NET returned.
so good so far you should definetely declare your webmethod as a method that returns a JSON format.
hope you found a solution before this answer...