Сериализация промежутка времени в словаре ‹строка, объект› с помощью Json.NET

У меня есть свойство, которое на самом деле является словарем. И я храню в этом словаре много типов, таких как TimeSpans, DateTimes и т. Д. Но сериализация и десериализация TimeSpans неверны и десериализуется как строка.

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();

РЕЗУЛЬТАТЫ: Типы объектов

Таким образом, TimeSpan в объекте не может десериализоваться до временного интервала. Я тоже пробовал с последней версией Json.Net. Но результат такой же.

Как я могу указать имя типа для TimeSpan? Или стоит написать кастомный конвертер и как?

Изменить:

Я провел несколько тестов и изменил сериализованное свойство timeSpan следующим образом:

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

и на этот раз json.net может десериализовать его как TimeSpan. Но как я могу указать $ type и $ value TimeSpan на уровне сериализации, как это?


person oruchreis    schedule 14.01.2013    source источник


Ответы (3)


Наконец-то я нашел решение. Я написал собственный конвертер для TimeSpan. Но я думаю, что в Json.Net есть ошибка. Потому что я бы не стал писать конвертер для примитивных типов, таких как TimeSpan. В любом случае вот решение:

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;
    }   
}

Также не забудьте добавить этот конвертер в настройки сериализатора json. Приветствуется любое лучшее решение, если оно есть.

person oruchreis    schedule 14.01.2013

Я также столкнулся с этой проблемой с System.Guid в качестве типа значения в словаре.

Я зарегистрировал эту ошибку в системе отслеживания проблем Json.NET.

person user1986235    schedule 25.01.2013

Я немного покопался и выяснил основную проблему - это происходит для любого типа, который DefaultContractResolver.CanConvertToString() Json.NET возвращает true. См. Здесь: Существенная ошибка в сериализации словаря Json.NET

К сожалению, в настоящее время автор считает это не ошибкой. Я думаю, что Json.NET - это круто, но эта проблема меня до чертиков пугает ...

Вот обсуждение на странице ошибки: https://json.codeplex.com/workitem/23833

person aggieNick02    schedule 08.04.2013