DataContractJsonSerializer во время десериализации преобразует значения DateTime в словари - PullRequest
0 голосов
/ 08 января 2019

Мне нужен сериализатор / десериализатор JSON, который поставляется с .NET. Я не могу использовать Newtonsoft Json.NET.

Насколько я знаю, это оставляет меня с JavaScriptSerializer и DataContractJsonSerializer . JavaScriptSerializer не работал должным образом, потому что он настаивает на каком-то глупом формате для datetime, который теряет смещение UTC после десериализации, не обращайте на это внимания.

Я использую DataContractJsonSerializer , и метод проверки ниже показывает, что не так. Я указываю пользовательский формат даты (ISO) для сериализации и десериализации, и строка выглядит хорошо. Кроме того, он читается Json.NET правильно.

Как я могу эффективно и в общем случае обойти эту проблему, без выполнения регулярных выражений и ручных преобразований?

[Test]
    public void SerializerFailure()
    {
       TestObject testObject = new TestObject() {Dict = new Dictionary<string, object>() {{"DateTest", DateTime.UtcNow}, {"DecimalTest", 66.6M}}};
        Assert.IsInstanceOf<DateTime>(testObject.Dict["DateTest"]);

        string serialized = this.Serialize(testObject);
        //output is OK...

        //{"Dict":{"DateTest":"2019-01-07T23:16:59.5142225Z","DecimalTest":66.6}}
        TestObject deserialized = this.Deserialize<TestObject>(serialized);
        Assert.IsInstanceOf<string>(deserialized.Dict["DateTest"]);

        TestObject newtonDeserialized = JsonConvert.DeserializeObject<TestObject>(serialized);
        testObject.ShouldBeEquivalentTo(newtonDeserialized); //passes OK


        testObject.ShouldBeEquivalentTo(deserialized); //Fails

        //ERROR: Expected member Dict[DateTest] to be 
        //      "2019-01-07T23:27:23.0758967Z" with a length of 28, but
        //      "07.01.2019 23:27:23" has a length of 19.
        //          Expected member Dict[DateTest] to be
        //      "2019-01-07T23:27:23.0758967Z", but
        //      "07.01.2019 23:27:23" differs near "07."(index 0).

    }

Сериализация:

    public string Serialize(object objectToPost)
    {
        using (MemoryStream stream = new System.IO.MemoryStream())
        {
            var settings = new DataContractJsonSerializerSettings() { DateTimeFormat = new DateTimeFormat("O"), UseSimpleDictionaryFormat = true };

            DataContractJsonSerializer serializer
                = new DataContractJsonSerializer(objectToPost.GetType(), settings);
            serializer.WriteObject(stream, objectToPost);
            stream.Flush();
            stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }

Десериализация

    public T Deserialize<T>(string stringContent)
    {
        try
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(stringContent)))
            {
                var settings = new DataContractJsonSerializerSettings() { DateTimeFormat = new DateTimeFormat("O"), UseSimpleDictionaryFormat = true };
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings);
                return (T)serializer.ReadObject(ms);
            }
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"Error while deserializing string as {typeof(T).Name}", ex);
        }

    }
...