ASP.NET MVC:用JsonResult控制属性名的序列化。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET MVC:用JsonResult控制属性名的序列化。相关的知识,希望对你有一定的参考价值。

有什么方法可以控制 JsonResult 属性,类似于你如何使用 XmlElementAttribute 及其兄弟类来控制XML序列化的输出?

例如,给定以下类。

public class Foo
{
    [SomeJsonSerializationAttribute("bar")]
    public String Bar { get; set; }

    [SomeJsonSerializationAttribute("oygevalt")]
    public String Oygevalt { get; set; }
}

我想得到以下的输出。

{ bar: '', oygevalt: '' }

而不是:

{ Bar: '', Oygevalt: '' }
答案

我想要比Jarrett建议的更多一点的东西融入到框架中,所以我是这样做的。

JsonDataContractActionResult:

public class JsonDataContractActionResult : ActionResult
{
    public JsonDataContractActionResult(Object data)
    {
        this.Data = data;
    }

    public Object Data { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        var serializer = new DataContractJsonSerializer(this.Data.GetType());
        String output = String.Empty;
        using (var ms = new MemoryStream())
        {
            serializer.WriteObject(ms, this.Data);
            output = Encoding.Default.GetString(ms.ToArray());
        }
        context.HttpContext.Response.ContentType = "application/json";
        context.HttpContext.Response.Write(output);
    }
}

JsonContract()方法,添加到我的基础控制器类中。

    public ActionResult JsonContract(Object data)
    {
        return new JsonDataContractActionResult(data);
    }

示例用法:"JsonContract() "方法,添加到我的基础控制器类中

    public ActionResult Update(String id, [Bind(Exclude="Id")] Advertiser advertiser)
    {
        Int32 advertiserId;
        if (Int32.TryParse(id, out advertiserId))
        {
            // update
        }
        else
        {
            // insert
        }

        return JsonContract(advertiser);
    }

注意: 如果你正在寻找比JsonDataContractSerializer更有性能的东西,你可以用JSON.NET来代替做同样的事情。虽然JSON.NET似乎没有利用DataMemberAttribute,但它有自己的JsonPropertyAttribute,可以用来完成同样的事情。

另一答案

这是我对Daniel Schaffer的答案的实现,并加入了Justin Rusbatch和Daniel的改进建议。

using System;
using System.Runtime.Serialization.Json;
using System.Web.Mvc;

public class JsonDataContractActionResult : JsonResult
{
    public JsonDataContractActionResult( Object data )
    {
        this.Data = data;
    }

    public override void ExecuteResult( ControllerContext context )
    {
        var serializer = new DataContractJsonSerializer( this.Data.GetType() );
        context.HttpContext.Response.ContentType = "application/json";
        serializer.WriteObject( context.HttpContext.Response.OutputStream, 
            this.Data );
    }
}
另一答案

我知道这是一个老问题,但对于那些正在寻找如何避免属性被序列化的人来说,可以使用 脚本IgnoreAttribute 在System.Web.Script.Serialization. 遗憾的是,仍然无法控制序列化属性的名称,但有人可能会觉得这很有帮助。

public class MyClass {

    [ScriptIgnoreAttribute]
    public bool PropertyNotSerialized { get; set; }

    public bool AnyProperty { get; set; }
}

将输出Json结果如下。

{"AnyProperty ": false}
另一答案

这是使用NewtonSoft Json.Net的解决方案(为了性能)我找到了部分解决方案 此处 和关于SO

public class JsonNetResult : ActionResult
    {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }

        public JsonSerializerSettings SerializerSettings { get; set; }
        public Formatting Formatting { get; set; }

        public JsonNetResult(object data, Formatting formatting)
            : this(data)
        {
            Formatting = formatting;
        }

        public JsonNetResult(object data):this()
        {
            Data = data;
        }

        public JsonNetResult()
        {
            Formatting = Formatting.None;
            SerializerSettings = new JsonSerializerSettings();
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            var response = context.HttpContext.Response;
            response.ContentType = !string.IsNullOrEmpty(ContentType)
              ? ContentType
              : "application/json";
            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if (Data == null) return;

            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);
            writer.Flush();
        }
    }

所以,在我的控制器中,我可以做到这一点。

        return new JsonNetResult(result);

在我的模型中,我现在可以有。

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }

注意,现在,你必须设置 JsonPropertyAttribute 到你想序列化的每个属性。

另一答案

简单的答案: DataContractJsonSerializer 应尊重 [DataContract][DataMember] 属性在BCL的System.Runtime.Serialization命名空间中。

另一答案

这些答案对我很有帮助,但比大家晚几年来解决这个问题,我发现这段代码在当前的框架版本下无法使用。 这个版本适用于Newtonsoft.Json和ASP NET Core 3.1。

/*
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
*/
public class JsonDataContractActionResult : IActionResult
{
    public JsonDataContractActionResult(object data) 
    {
        this.Data = data;
    }

    public object Data { get; private set; }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        context.HttpContext.Response.ContentType = "application/json";
        JsonSerializer serializer = new JsonSerializer();
        serializer.NullValueHandling = NullValueHandling.Ignore;
        using (MemoryStream ms = new MemoryStream()) {
            using (StreamWriter sw = new StreamWriter(ms))
            {
                using (JsonWriter writer = new JsonTextWriter(sw))
                {
                    serializer.Serialize(writer, Data);
                }
            }
            byte[] b = ms.ToArray();
            await context.HttpContext.Response.Body.WriteAsync(b);
        }
    }
}

以上是关于ASP.NET MVC:用JsonResult控制属性名的序列化。的主要内容,如果未能解决你的问题,请参考以下文章

加载 ASP.Net MVC JSONResult jQuery DataTables

ASP.NET MVC JsonResult 返回 500

csharp C#:JsonResult替代ASP.NET MVC。

ASP.NET MVC 下自定义 JsonResult,使用 Json.NET 序列化 JSON

ASP.Net MVC:如何基于原始Json数据创建JsonResult

asp.net mvc自定义JsonResult类来防止MaxJsonLength超过限制