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

xsl*_*xsl 15 serialization json properties asp.net-mvc-3

我想将一个简单的对象序列化为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; }
}
Run Code Online (Sandbox Code Playgroud)

但每当我这样做:

return Json(tree, JsonRequestBehavior.AllowGet);
Run Code Online (Sandbox Code Playgroud)

属性名称不作为指定[DataMember]部分,但类似的情况在类如直接定义的那些的SelectOnInit它不是select,但SelectOnInit.

我究竟做错了什么?

xsl*_*xsl 16

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

ASP.NET MVC:使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

    public ActionResult TestFunction()
    {
        var testObject = new TestClass();
        return new JsonDataContractActionResult(testObject);
    }
Run Code Online (Sandbox Code Playgroud)

我还必须修改初始类:

// -- 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; }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 10

这是一个使用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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

        return new JsonNetResult(result);
Run Code Online (Sandbox Code Playgroud)

在我的模型中,我现在可以:

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)

请注意,现在,您必须设置JsonPropertyAttribute要序列化的每个属性.