MVC3 JSON序列化:如何控制属性名称?

时间:2011-08-31 17:25:45

标签: json asp.net-mvc-3 serialization properties

我想将一个简单的对象序列化为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; }
}

但每当我这样做时:

return Json(tree, JsonRequestBehavior.AllowGet);

属性名称不在[DataMember]部分中指定,但类似于直接在类中定义的属性名称,例如在SelectOnInit的情况下,它不是select而是SelectOnInit

我做错了什么?

2 个答案:

答案 0 :(得分:16)

我通过使用此问题答案中提供的技术解决了这个问题:

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

以下是我的课程:

/// <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);
    }
}

用法:

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

我还必须修改初始类:

// -- 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; }
}

答案 1 :(得分:10)

这是一个使用newtonsoft Json.net的解决方案(针对性能而言)

我找到了解决方案的一部分here和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设置为要序列化的每个属性。