Json.NET does not store primitive type information in object lists or dictionaries. Is there a workaround?

The following example illustrates the fundamental drawback of handling Json.NET type types:

List<object> items = new List<object>() {Guid.NewGuid(),DateTime.Now}; var settings = new JsonSerializerSettings() { TypeNameHandling=TypeNameHandling.All }; var json = JsonConvert.SerializeObject<List<object>>(value,settings); 

which leads to the following JSON:

 {"$type":"System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib","$values":["9d7aa4d3-a340-4cee-baa8-6af0582b8acd","2014-07-28T21:03:17.1287029-04:00"]} 

As you can see, the list items have lost type information. Deserializing the same JSON will result in a list containing only strings.

This issue was previously reported by Codeplex and completely closed, stating, including type information, which would make JSON too confusing. I am surprised that we are not given a separate option to include information about the primitive type for such scenarios when there is a violation of consistency in a circle.

https://json.codeplex.com/workitem/23833

I would expect the data to return with the same type information with which it was left. Does anyone have any suggestions or workarounds to eliminate this unwanted behavior?

Thanks,

Chris

+6
source share
2 answers

Here is a solution using custom JsonConverter :

 public sealed class PrimitiveJsonConverter : JsonConverter { public PrimitiveJsonConverter() { } public override bool CanRead { get { return false; } } public override bool CanConvert(Type objectType) { return objectType.IsPrimitive; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { switch (serializer.TypeNameHandling) { case TypeNameHandling.All: writer.WriteStartObject(); writer.WritePropertyName("$type", false); switch (serializer.TypeNameAssemblyFormat) { case FormatterAssemblyStyle.Full: writer.WriteValue(value.GetType().AssemblyQualifiedName); break; default: writer.WriteValue(value.GetType().FullName); break; } writer.WritePropertyName("$value", false); writer.WriteValue(value); writer.WriteEndObject(); break; default: writer.WriteValue(value); break; } } } 

Here's how to use it:

 JsonSerializerSettings settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, }; settings.Converters.Insert(0, new PrimitiveJsonConverter()); return JsonConvert.SerializeObject(myDotNetObject, settings); 

I am currently using this solution to serialize an instance of IDictionary<string, object> , which may contain primitives.

+12
source

Hacked it together and checked it. Obviously, this requires unit testing and is more a proof of concept. If you want a dirty solution to get started, this should begin.

https://github.com/xstos/Newtonsoft.Json/commit/8d3507cbba78f7096a82e42973e56d69c9541c42

+1
source

Source: https://habr.com/ru/post/973001/


All Articles