ASP.NET MVC: control de la serialización de los nombres de propiedades con JsonResult

¿Hay alguna forma de controlar la salida JSON de JsonResult con atributos, similar a cómo se puede usar XmlElementAttribute y sus bretheren para controlar el resultado de la serialización XML?

Por ejemplo, dada la siguiente clase:

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

Me gustaría obtener el siguiente resultado:

 { bar: '', oygevalt: '' } 

Opuesto a:

 { Bar: '', Oygevalt: '' } 

Quería algo más elaborado en el marco que lo que sugirió Jarrett, así que esto es lo que hice:

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

Método JsonContract (), agregado a mi clase de controlador base:

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

Uso de la muestra:

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

Nota: Si está buscando algo más eficiente que JsonDataContractSerializer, puede hacer lo mismo con JSON.NET. Aunque JSON.NET no parece utilizar DataMemberAttribute, sí tiene su propio JsonPropertyAttribute que se puede usar para lograr lo mismo.

Aquí está mi implementación de la respuesta de Daniel Schaffer, con las mejoras sugeridas por Justin Rusbatch y Daniel incorporadas.

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

Sé que esta es una vieja pregunta, pero para aquellos que buscan cómo evitar que las propiedades se serialicen, use ScriptIgnoreAttribute en el espacio de nombres System.Web.Script.Serialization. Lamentablemente todavía no se puede controlar el nombre de las propiedades serializadas, pero alguien puede encontrar esto útil.

 public class MyClass { [ScriptIgnoreAttribute] public bool PropertyNotSerialized { get; set; } public bool AnyProperty { get; set; } } 

La salida como Json dará como resultado lo siguiente:

 {"AnyProperty ": false} 

Esta es la solución para usar NewtonSoft Json.Net (para el rendimiento) He encontrado parte de la solución aquí y en 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(); } } 

Entonces en mi controlador, puedo hacer eso

  return new JsonNetResult(result); 

En mi modelo, ahora puedo tener:

  [JsonProperty(PropertyName = "n")] public string Name { get; set; } 

Tenga en cuenta que ahora debe establecer JsonPropertyAttribute en cada propiedad que desee serializar.

Respuesta fácil: el DataContractJsonSerializer debe respetar los atributos [DataContract] y [DataMember] en el espacio de nombres System.Runtime.Serialization del BCL.