ASP.NET MVC: Controlling serialization of property names with JsonResult

后端 未结 6 740
执笔经年
执笔经年 2020-11-27 05:33

Is there a way to control the JSON output of JsonResult with attributes, similar to how you can use XmlElementAttribute and its bretheren to contro

相关标签:
6条回答
  • Here's my implementation of Daniel Schaffer's answer, with the suggested improvements by Justin Rusbatch and Daniel incorporated.

    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 );
        }
    }
    
    0 讨论(0)
  • 2020-11-27 05:59

    This is the solution to use NewtonSoft Json.Net (for performance) I've found part of the solution here and on 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();
            }
        }
    

    So that in my controller, I can do that

            return new JsonNetResult(result);
    

    In my model, I can now have:

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

    Note that now, you have to set the JsonPropertyAttribute to every property you want to serialize.

    0 讨论(0)
  • 2020-11-27 06:02

    These answers were helpful to me, but coming to this problem a few years later than everyone else I found that this code didn't work with the current framework version. This version works with Newtonsoft.Json and 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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 06:09

    I wanted something a bit more baked into the framework than what Jarrett suggested, so here's what I did:

    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() method, added to my base controller class:

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

    Sample Usage:

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

    Note: If you're looking for something more performant than JsonDataContractSerializer, you can do the same thing using JSON.NET instead. While JSON.NET doesn't appear to utilize DataMemberAttribute, it does have its own JsonPropertyAttribute which can be used to accomplish the same thing.

    0 讨论(0)
  • 2020-11-27 06:14

    I know this is an old question but for those looking for just how to avoid properties from being serialized use the ScriptIgnoreAttribute in the namespace System.Web.Script.Serialization. Sadly still can't controll the name of the serialized properties but somebody might find this helpfull.

    public class MyClass {
    
        [ScriptIgnoreAttribute]
        public bool PropertyNotSerialized { get; set; }
    
        public bool AnyProperty { get; set; }
    }
    

    Will output as Json result the following:

    {"AnyProperty ": false}
    
    0 讨论(0)
  • 2020-11-27 06:14

    Easy answer: the DataContractJsonSerializer should respect the [DataContract] and [DataMember] attributes in the System.Runtime.Serialization namespace of the BCL.

    0 讨论(0)
提交回复
热议问题