【问题标题】:MVC JsonNetResult - "dataloss" when serializing List<ListItem>MVC JsonNetResult - 序列化 List<ListItem> 时出现“数据丢失”
【发布时间】:2014-07-21 08:30:30
【问题描述】:

我已经用 ASP.NET MVC 覆盖了默认的 Json 序列化器:

public class JsonNetResult : JsonResult
{
    public JsonNetResult()
    {
        Settings = new JsonSerializerSettings
                       {
                           ReferenceLoopHandling = ReferenceLoopHandling.Error,
                       };
    }

    public JsonSerializerSettings Settings { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException("JSON GET is not allowed");

        HttpResponseBase response = context.HttpContext.Response;
        response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;

        if (this.ContentEncoding != null)
            response.ContentEncoding = this.ContentEncoding;
        if (this.Data == null)
            return;

        var scriptSerializer = JsonSerializer.Create();

        using (var sw = new StringWriter())
        {
            scriptSerializer.Serialize(sw, this.Data);
            response.Write(sw.ToString());
        }
    }
}

当我序列化以下内容时:

public JsonResult GetLevels()
    {
        List<ListItem> items = new List<ListItem>();
        items.Add(new ListItem() { Text = "Home", Value = "5"});
        items.Add(new ListItem() { Text = "Live", Value = "6"});
        items.Add(new ListItem() { Text = "Dev", Value = "7"});
        items.Add(new ListItem() { Text = "Staging", Value = "8"});

        return Json(items, JsonRequestBehavior.AllowGet);
    }

我得到的 JavaScript 对象如下:

级别:数组[4] 0:“家” 1:“现场” 2:“开发” 3:“分期”

所以在这里我所有的信息都像价值一样丢失了。 但是当我使用 Default Json 序列化程序时,我得到了“正确”的信息序列化

级别: 数组[4]

0:对象 属性:对象 启用:真 选择:假 文字:“家” 值:“5”

1:对象 属性:对象 启用:真 选择:假 文字:《活着》 值:“6” ...

但由于 DateTime 序列化,我需要使用自定义序列化程序。 但我不知道我在自定义 JsonNetResult 上做错了什么或我错过了什么。因为这里有数据丢失或者是不正常的?

【问题讨论】:

  • 当我使用 Text 和 Value 创建自己的 .NET Helper 类时,一切正常,但是当我使用 .NET 类 ListItem 时,序列化将不起作用 - 很奇怪
  • 我也有同样的问题。你找到答案了吗?
  • 嗨,就像我在另一条评论中写的那样 - 我已经编写了自己的 Helper 类 - 然后一切正常。
  • @David 我添加了一个解决方案,以防您仍然感兴趣。

标签: c# asp.net-mvc json serialization


【解决方案1】:

出现此问题是因为ListItem 类应用了[TypeConverter] 属性。当 Json.Net 看到这一点时,它使用关联的 TypeConverter 来获取值,而不是将其序列化为普通对象。在这种情况下,TypeConverter 将 ListItem 转换为一个简单的字符串,这就是为什么您没有得到您期望的完整序列化的原因。 JavaScriptSerializer(MVC 使用的默认序列化器)不做这个检查,所以 ListItem 在这种情况下会正常序列化。

您可以使用自定义 ContractResolver 来告诉 Json.Net 将 ListItem 序列化为对象,而不是使用 TypeConverter。这是您需要的代码:

class CustomContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (objectType == typeof(ListItem))
            return base.CreateObjectContract(objectType);

        return base.CreateContract(objectType);
    }
}

将解析器添加到您的JsonSerializerSettings,您应该准备好了:

Settings = new JsonSerializerSettings
{
    ContractResolver = new CustomContractResolver(),
    ...        
};

注意:请确保在创建 JsonSerializer 时将设置传递给它 - 在您的代码中看起来您并没有这样做。

var scriptSerializer = JsonSerializer.Create(Settings);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 2012-05-14
    • 2011-06-24
    相关资源
    最近更新 更多