Serializing Timespan in Dictionary<string, object> with Json.NET

主宰稳场 提交于 2021-02-16 14:21:46

问题


I have a property that is actually a Dictionary. And I keep many types in this dictionary like TimeSpans, DateTimes, etc. But serializing and deserializing TimeSpans are wrong and it deserializes as string.

var dict = new Dictionary<string, object>();
dict.Add("int", 15);
dict.Add("string", "foo");
dict.Add("timeSpan", new TimeSpan(1,1,1));
dict.Add("dateTime", DateTime.Now);

var settings = new JsonSerializerSettings{
    TypeNameHandling = TypeNameHandling.All,
        TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
};
var serializedObj = JsonConvert.SerializeObject(dict, Newtonsoft.Json.Formatting.Indented, settings);
var deserializedObj = (Dictionary<string, object>)JsonConvert.DeserializeObject(serializedObj, settings);
//Displaying the types with LinqPad:
deserializedObj["int"].GetType().Dump();
deserializedObj["string"].GetType().Dump();
deserializedObj["timeSpan"].GetType().Dump();
deserializedObj["dateTime"].GetType().Dump();

RESULTS: Types of the objects

So TimeSpan in an object can't deserialize to a timespan. I've tried with latest version of Json.Net too. But the result is same.

How can I specify type name for TimeSpan? Or should I write a custom converter and how?

Edit:

I did some tests and I changed serialized timeSpan property like this:

""timeSpan"": {
    ""$type"": ""System.TimeSpan"",
    ""$value"": ""01:01:01""}

and this time json.net could desrialize it as TimeSpan. But How can I specify $type and $value of TimeSpan at Serialization level like this?


回答1:


I've finally found a solution. I've written a custom converter for TimeSpan. But I think there is a bug in Json.Net. Because I wouldn't write a converter for primitive types like TimeSpan. Anyway here is the solution:

public class TimeSpanConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(TimeSpan);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        writer.WritePropertyName("$type");
        writer.WriteValue(value.GetType().FullName);
        writer.WritePropertyName("$value");
        writer.WriteValue(value);
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type type, object value, JsonSerializer serializer)
    {
        return value;
    }   
}

Also don't forget to add this converter to json serializer settings. Any better solution is appreciated, if there is any.




回答2:


I also run into this issue with System.Guid as the value type in the dictionary.

I filed this bug in the Json.NET issue tracker.




回答3:


I dug a bit and figured out the underlying issue - it happens for any type which Json.NET's DefaultContractResolver.CanConvertToString() returns true. See here: Significant bug in Json.NET dictionary serialization

Unfortunately it is currently considered not a bug by the author. I think Json.NET is awesome, but this issue scares the heck out of me...

Here's the discussion on the bug page: https://json.codeplex.com/workitem/23833



来源:https://stackoverflow.com/questions/14316637/serializing-timespan-in-dictionarystring-object-with-json-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!