Newtonsoft.json: Guid support for Object array.

Created on 2 Dec 2015  路  5Comments  路  Source: JamesNK/Newtonsoft.Json

The next example does not work because Guid is deserialized as String:

``` C#
using Newtonsoft.Json;
using System;

public class Request
{
public Request()
{
Arguments = new Object[3];
}
public object[] Arguments { get; set; }
}

public class Program
{
public static void Main()
{
Request r = new Request();
r.Arguments[0] = Guid.NewGuid();
r.Arguments[1] = AnyOtherClass();
string output = JsonConvert.SerializeObject(r, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(output);
Request deserializedRequest = JsonConvert.DeserializeObject(output, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(output);
Console.WriteLine(deserializedRequest.Arguments[0].GetType()); //String!!!
Console.WriteLine(((Guid)deserializedRequest.Arguments[0])); //Error!!! (of course)
Console.ReadKey();
}
}
```

I am working in a fix in my own fork (https://github.com/jlvaquero/Newtonsoft.Json). Seems to works well but I am not sure if I am in the right path and if I am missing something. Could anyone check it out and provides me some guidance and/or contribute into my fork? Later, when everything is complete and stable, we could pull request if the owners of this repository are interested.

Most helpful comment

This is very odd resolution of the issue (considering original code as posted) -- truly, you cannot say looking at string that is is GUID and not string, but please note the type name handling should kick in, and decoration should be added for every entry of the array, not only array as a whole. Since you have declaration of object[] what you declared is that each element is an object. And since there is mismatch (when serializing) between declared type of the element and actual type, for type name handling set as All and Objects the type should be added per element as well.

With type name handling in place, deserialization would be straightforward -- you see decoration GUID and you proceed accordingly.

Please reconsider reopening this issue.

All 5 comments

This is just a limitation of JSON - the type system isn't rich enough to round trip every kind of data, e.g. the difference between int and long, double and decimal, string and GUID, etc.

But for DateTime you did a tryConvert before treat the data as string and works well. It was a good idea. I just did the same thing for Guid in my fork and seems to be OK. Did you check it out?

That will be a breaking change for anyone who currently casts the object to string. And if this is done for GUID, why not also Uri, TimeSpan, base64 text to bytes, etc.

You can do this yourself with a JsonConverter.

This is very odd resolution of the issue (considering original code as posted) -- truly, you cannot say looking at string that is is GUID and not string, but please note the type name handling should kick in, and decoration should be added for every entry of the array, not only array as a whole. Since you have declaration of object[] what you declared is that each element is an object. And since there is mismatch (when serializing) between declared type of the element and actual type, for type name handling set as All and Objects the type should be added per element as well.

With type name handling in place, deserialization would be straightforward -- you see decoration GUID and you proceed accordingly.

Please reconsider reopening this issue.

While I'm not sure what's the best solution to tackle this problem, I think the documentation of TypeNameHandling.All is misleading. It does not "Always include the .NET type" - AFAIU, it does so only for .NET objects that are serialized into JSON objects or JSON arrays.

Maybe it would be a good idea to add more TypeNameHandling values to allow the user to mimic the same behavior for other types?

For example, serializing with TypeNameHandling = TypeNameHandling.Strings | TypeNameHandling.Numbers could result in:

[
  {
    "$type": "System.Guid, mscorlib",
    "$value": "f97a6843-8708-456b-afe9-679410f55496"
  },

  {
    "$type": "System.Int64, mscorlib",
    "$value":  7
  }
]

Was this page helpful?
0 / 5 - 0 ratings