2009-08-19 108 views
31

有没有一种方法可以控制具有属性的JsonResult的JSON输出,类似于您可以如何使用XmlElementAttribute及其brethren来控制XML序列化的输出?ASP.NET MVC:使用JsonResult控制属性名称的序列化

例如,给定下面的类:

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

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

我想,然后得到以下的输出:

{ bar: '', oygevalt: '' } 

至于反对:

{ Bar: '', Oygevalt: '' } 
+0

检查出新发布的Sierra:http://kohari.org/2009/08/10/siesta-painless-rest-via-asp-net-mvc/ – 2009-08-19 22:28:29

+1

这看起来很有前途(也很有趣!),但是我希望获得已经出炉的东西。任何方式让现有的序列化器尊重DataContract属性? – 2009-08-19 22:34:52

回答

38

我想有些东西比Jarrett建议的要多一点,所以这就是我所做的:

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()方法,添加到我的基本控制器类:

public ActionResult JsonContract(Object data) 
    { 
     return new JsonDataContractActionResult(data); 
    } 

示例用法:

public ActionResult Update(String id, [Bind(Exclude="Id")] Advertiser advertiser) 
    { 
     Int32 advertiserId; 
     if (Int32.TryParse(id, out advertiserId)) 
     { 
      // update 
     } 
     else 
     { 
      // insert 
     } 

     return JsonContract(advertiser); 
    } 

注意:如果您正在寻找比JsonDataContractSerializer更高性能的东西,那么您可以使用JSON.NET来做同样的事情。虽然JSON.NET似乎没有使用DataMemberAttribute,但它有自己的JsonPropertyAttribute,可以用来完成同样的事情。

+1

关于MVC的真棒部分是这些东西是多么容易写。你可以很快把一些非常复杂的解决方案放在一起! – 2009-08-20 00:24:03

+1

事实确实如此!我不打算回头看WebForms。 – 2009-08-20 01:27:43

+0

非常好的解决方案!如果从'JsonResult'继承而不是''ActionResult''基类,'JsonDataContractActionResult'类可以进一步简化 - 那么您只需要重写'ExecuteResult'方法! – 2011-03-03 15:52:46

1

简单回答:DataContractJsonSerializer应该尊重BCL的System.Runtime.Serialization命名空间中的[DataContract][DataMember]属性。

+15

对于那些不知情的人来说,Nate表达了MVC的-desired-行为,而不是今天MVC的实际行为。从MVC2开始,MVC使用JavaScriptSerializer,它不支持WCF DataContract序列化器支持的DataMember属性。今天需要一个自定义的ActionResult来使MVC使用DataContract/DataMember属性。 – Todd 2010-12-08 23:15:38

16

下面是我对Daniel Schaffer的回答的实现,以及Justin Rusbatch和Daniel合并的建议改进。

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); 
    } 
} 
+0

+1 - 尽我所知,DataContractJsonSerializer仍然不是直接受支持的MVC 4,所以这是一个优雅的解决方案。 – 2012-08-06 04:00:34

5

我知道这是一个老问题,但对于那些寻找只是如何避免被命名空间中的System.Web.Script.Serialization系列化使用ScriptIgnoreAttribute性能。遗憾的是仍然无法控制序列化属性的名称,但有人可能会发现这个有用的。

public class MyClass { 

    [ScriptIgnoreAttribute] 
    public bool PropertyNotSerialized { get; set; } 

    public bool AnyProperty { get; set; } 
} 

威尔输出作为JSON结果如下:

{"AnyProperty ": false} 
+0

我可以证实这一点。该名称空间位于System.Web.Extensions程序集中。 – 2013-07-29 16:10:45

+0

完美... Tanx很多,它工作正常... – 2015-01-26 13:45:52

3

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

+0

谢谢万元 – 2017-02-21 09:53:50

相关问题