Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 JSON Serialization: How to control the property names?

I want to serialize a simple object to JSON:

public class JsonTreeNode
{
    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "isFolder")]
    public bool IsFolder { get; set; }

    [DataMember(Name = "key")]
    public string Key { get; set; }

    [DataMember(Name = "children")]
    public IEnumerable<JsonTreeNode> Children { get; set; }

    [DataMember(Name = "select")]
    public bool SelectedOnInit { get; set; }
}

But whenever I do it:

return Json(tree, JsonRequestBehavior.AllowGet);

The property names are not as specified in the [DataMember] section, but similar to the ones defined directly in the class e.g. in the case of SelectOnInit it is not select but SelectOnInit.

What am I doing wrong?

like image 285
xsl Avatar asked Aug 31 '11 17:08

xsl


People also ask

What is a JSON property name?

Objects are the mapping type in JSON. They map “keys” to “values”. In JSON, the “keys” must always be strings. Each of these pairs is conventionally referred to as a “property”.

How does the JsonProperty attribute affect JSON serialization?

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.

What is JsonExtensionData?

[JsonExtensionData] allows you to do is to serialize elements of a JSON document which does not have matching properties on the destination object to the dictionary which is decorated with the [JsonExtensionData] attribute.


1 Answers

I solved the problem by using the technique provided in the answer in this question:

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

Here is the class I made:

/// <summary>
/// Similiar to <see cref="JsonResult"/>, with
/// the exception that the <see cref="DataContract"/> attributes are
/// respected.
/// </summary>
/// <remarks>
/// Based on the excellent stackoverflow answer:
/// https://stackoverflow.com/a/263416/1039947
/// </remarks>
public class JsonDataContractActionResult : ActionResult
{
    /// <summary>
    /// Initializes a new instance of the class.
    /// </summary>
    /// <param name="data">Data to parse.</param>
    public JsonDataContractActionResult(Object data)
    {
        Data = data;
    }

    /// <summary>
    /// Gets or sets the data.
    /// </summary>
    public Object Data { get; private set; }

    /// <summary>
    /// Enables processing of the result of an action method by a 
    /// custom type that inherits from the ActionResult class. 
    /// </summary>
    /// <param name="context">The controller context.</param>
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var serializer = new DataContractJsonSerializer(Data.GetType());

        string output;
        using (var ms = new MemoryStream())
        {
            serializer.WriteObject(ms, Data);
            output = Encoding.UTF8.GetString(ms.ToArray());
        }

        context.HttpContext.Response.ContentType = "application/json";
        context.HttpContext.Response.Write(output);
    }
}

Usage:

    public ActionResult TestFunction()
    {
        var testObject = new TestClass();
        return new JsonDataContractActionResult(testObject);
    }

I also had to modify the initial class:

// -- The DataContract property was added --
[DataContract]
public class JsonTreeNode
{
    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "isFolder")]
    public bool IsFolder { get; set; }

    [DataMember(Name = "key")]
    public string Key { get; set; }

    [DataMember(Name = "children")]
    public IEnumerable<JsonTreeNode> Children { get; set; }

    [DataMember(Name = "select")]
    public bool SelectedOnInit { get; set; }
}
like image 135
xsl Avatar answered Sep 20 '22 15:09

xsl