Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

For example, given the following class:

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

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

I'd like to then get the following output:

{ bar: '', oygevalt: '' }

As opposed to:

{ Bar: '', Oygevalt: '' }
like image 238
Daniel Schaffer Avatar asked Aug 19 '09 22:08

Daniel Schaffer


People also ask

What is the use of JsonResult in MVC?

What is JsonResult ? JsonResult is one of the type of MVC action result type which returns the data back to the view or the browser in the form of JSON (JavaScript Object notation format).

What is the difference between ActionResult and JsonResult?

Use JsonResult when you want to return raw JSON data to be consumed by a client (javascript on a web page or a mobile client). Use ActionResult if you want to return a view, redirect etc to be handled by a browser.

What is JSON property name?

The Jackson Annotation @JsonProperty is used on a property or method during serialization or deserialization of JSON. It takes an optional 'name' parameter which is useful in case the property name is different than 'key' name in JSON.

What is JSON Property C#?

JsonPropertyAttribute indicates that a property should be serialized when member serialization is set to opt-in. It includes non-public properties in serialization and deserialization. It can be used to customize type name, reference, null, and default value handling for the property value.


4 Answers

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.

like image 139
Daniel Schaffer Avatar answered Oct 12 '22 09:10

Daniel Schaffer


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 );
    }
}
like image 16
Katie Kilian Avatar answered Oct 12 '22 07:10

Katie Kilian


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.

like image 6
Daniel Avatar answered Oct 12 '22 07:10

Daniel


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}
like image 5
Danny Pérez Avatar answered Oct 12 '22 08:10

Danny Pérez