【问题标题】:MVC3 JSON Serialization: How to control the property names?MVC3 JSON 序列化:如何控制属性名称?
【发布时间】:2011-08-31 17:25:44
【问题描述】:

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

我做错了什么?

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      这是一个使用 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 设置为要序列化的每个属性。

      【讨论】:

      • 优秀的答案。我想知道为什么它没有被太多投票。当我们使用 Newtonsoft 时,它肯定会提高性能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 2020-04-28
      • 2019-12-27
      • 2013-10-11
      相关资源
      最近更新 更多