反序列化Json对象 - DateTime

7
我的web-api返回一个用户对象,在该对象中有一个DateTime属性。当我在应用程序中读取它时,会出现错误,因为表示DateTime的字符串无效,缺少\Date...。
{System.Runtime.Serialization.SerializationException:反序列化类型为User的对象时出错。 DateTime内容“1984-10-02T01:00: 00”不以所需的JSON格式“/ Date()”开头和结尾。 --->}
public static async Task<User> GetUser(string email)
    {
        try
        {
            using (HttpClient client = new HttpClient())
            {
                HttpResponseMessage response = await client.GetAsync(url + "?email="+email);
                if (response.IsSuccessStatusCode)
                {
                    string content = await response.Content.ReadAsStringAsync();
                    User user = DataService.Deserialize<User>(content);
                    return user;
                }
                return null;
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }

这是我用来反序列化的方法。

public static T Deserialize<T>(string json) {
        try
        {
            var _Bytes = Encoding.Unicode.GetBytes(json);
            using (MemoryStream _Stream = new MemoryStream(_Bytes))
            {

                var _Serializer = new DataContractJsonSerializer(typeof(T));

                return (T)_Serializer.ReadObject(_Stream);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
5个回答

9
为了解决这个问题,可能最简单的方法是将您的DataContract类型的值类型设置为“string”。然后,如果您需要使用.NET日期时间进行操作,您需要对字符串值进行DateTime.Parse。这将消除您的反序列化问题。很可能最初序列化的类本来就使用字符串值,因为它缺少日期的必要格式。
请注意,当您执行DateTime.Parse时,如果存在时区信息,它将转换为计算机的本地时间(这很愚蠢,我知道)。只是提供一下信息。

1
这对我有用。例如:DateTime.Parse("2014-11-04T05:00:00.000Z"); - Jerther

8

在JSON规范中,没有标准的日期交换格式, 这就是为什么JSON中有许多不同的异构日期格式的原因!

DataContractJsonSerializer将日期序列化为自1970年以来计算毫秒数的格式,用Date()括起来,类似于这样:Date(1335205592410),并期望相同的格式反序列化回DateTime。然而,作为JSON日期字符串获取的内容是ISO8601格式,这是大多数浏览器/软件今天用于序列化日期的格式!

JavaScriptSerializer是.Net中的另一种JSON序列化程序,它可以序列化任何类型,包括匿名类型到或从JSON字符串,并且能够反序列化JSON日期,无论是ISO8601格式还是DataContractJsonSerializer提供的格式。

使用JavaScriptSerializer,您的Deserialize方法将如下所示:

public static T Deserialize<T>(string json)
{
    return new JavaScriptSerializer().Deserialize<T>(json);
}

JavaScriptSerializer在w8应用程序中不存在,现在怎么办?有Nuget包或其他东西吗? - Sam_vdd
2
如果您的应用程序是使用 .Net 4.5 的 WPF/Winforms,只需添加对 System.Web.Extensions 的引用即可。但是,如果您正在开发 WinRT 应用程序,则可以使用 System.Web.Extensions.dll 或第三方库,例如在此处找到的 JSON.net:http://nuget.org/packages/Newtonsoft.Json。 - Kamyar Nazeri

7

当添加Json.net(Newtonsoft.Json)包时,我发现了如何修复它的方法。

public async static Task<T> Deserialize<T>(string json)
    {
        var value = await Newtonsoft.Json.JsonConvert.DeserializeObjectAsync<T>(json);
        return value;
    }

你能详细解释一下这应该在哪里使用吗? - Gabriel Luca

1

只需像这样更改DataContractJsonSerializer上的DateTimeFormat:

    public static T Deserialize<T>(string json) {
    try
    {
        var settings = new DataContractJsonSerializerSettings 
        {
            DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("o")
        };
        var _Bytes = Encoding.Unicode.GetBytes(json);
        using (MemoryStream _Stream = new MemoryStream(_Bytes))
        {

            var _Serializer = new DataContractJsonSerializer(typeof(T), settings);

            return (T)_Serializer.ReadObject(_Stream);
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

我尝试了这段代码,但似乎对我无效。 - Joel Barsotti

1

DateTime是否实际上返回为“可空类型”,比如“DateTime?”(带有问号)?

因为这样的话,它可能是NULL,就像“.HasValue == false”一样。

只是猜测而已... :-)


没有,它得到了正确的值“1984-10-02T01:00:00”,只是以另一种格式。 - Sam_vdd
似乎DateTime的默认序列化格式。所以你遇到异常很奇怪。也许尝试在序列化和反序列化时使用Utf8而不是Unicode?我自己从未遇到过这个问题。 - Mats Magnem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接