2009-08-19 10 views
31

Gibt es eine Möglichkeit, die JSON-Ausgabe von JsonResult mit Attributen zu steuern, ähnlich wie Sie XmlElementAttribute und seine bretheren verwenden, um die Ausgabe von XML-Serialisierung zu steuern?ASP.NET MVC: Steuern der Serialisierung von Eigenschaftsnamen mit JsonResult

Zum Beispiel angesichts der folgenden Klasse:

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

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

Ich mag würde, um dann die folgende Ausgabe:

{ bar: '', oygevalt: '' } 

Im Gegensatz zu:

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

Schauen Sie sich die neu veröffentlichten Sierra: http://kohari.org/2009/08/10/siesta-painless-rest-via-asp-net-mvc/ –

+1

Das sieht vielversprechend (und interessant!), Aber ich Ich habe auf etwas gehofft, das bereits vorhanden ist. Kann ich den vorhandenen Serializer dazu bringen, die DataContract-Attribute zu respektieren? –

Antwort

38

Ich wollte etwas, das etwas mehr in den Rahmen eingebacken ist als das, was Jarrett vorgeschlagen hat, also hier ist, was ich getan habe:

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() Methode, hinzugefügt, um meine Basis Controller-Klasse:

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

Verwendungsbeispiel:

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

     return JsonContract(advertiser); 
    } 

Hinweis: Wenn Sie nach etwas performanterem als JsonDataContractSerializer suchen, können Sie dasselbe mit JSON.NET tun. Während JSON.NET DataMemberAttribute nicht zu verwenden scheint, hat es sein eigenes JsonPropertyAttribute, das verwendet werden kann, um dasselbe zu erreichen.

+1

Das Tolle an MVC ist, wie leicht es ist, zu schreiben. Sie können ziemlich schnell anspruchsvolle Lösungen zusammenstellen! –

+1

In der Tat ist es! Ich habe nicht vor, jemals auf WebForms zurückzublicken. –

+0

Sehr schöne Lösung! Die 'JsonDataContractActionResult'-Klasse kann noch weiter vereinfacht werden, wenn Sie anstelle der Basis' ActionResult 'von' JsonResult 'erben - dann müssen Sie nur die 'ExecuteResult'-Methode überschreiben! –

1

Einfache Antwort: Die DataContractJsonSerializer sollte die Attribute [DataContract] und [DataMember] im Namensraum System.Runtime.Serialization des BCL berücksichtigen.

+15

Um für diejenigen, die es nicht wissen, klar zu sein, drückt Nate das gewünschte Verhalten von MVC aus, nicht das tatsächliche Verhalten von MVC heute. Ab MVC2 verwendet MVC den JavaScriptSerializer, der die vom WCF DataContract-Serializer unterstützten DataMember-Attribute nicht unterstützt. Ein benutzerdefiniertes ActionResult ist heute erforderlich, damit MVC die DataContract/DataMember-Attribute verwendet. – Todd

16

Hier ist meine Umsetzung von Daniel Schaffer die Antwort, mit den vorgeschlagenen Verbesserungen von Justin Rusbatch und Daniel eingearbeitet.

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 - wie ich sehen kann, wird der 'DataContractJsonSerializer' in MVC 4 immer noch nicht direkt unterstützt, also ist dies eine elegante Lösung. –

5

Ich weiß, dass dies eine alte Frage, aber für diejenigen, die gerade auf der Suche, wie Eigenschaften zu vermeiden, serialisiert Verwendung ist die ScriptIgnoreAttribute im Namensraum System.Web.Script.Serialization. Leider kann ich den Namen der serialisierten Eigenschaften nicht kontrollieren, aber jemand könnte das hilfreich finden.

public class MyClass { 

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

    public bool AnyProperty { get; set; } 
} 

ausgegeben als Json Ergebnis folgendes:

{"AnyProperty ": false} 
+0

Ich kann bestätigen, dass dies funktioniert. Dieser Namespace befindet sich in der System.Web.Extensions-Assembly. –

+0

Perfekt ... Tanx viel, Es funktioniert einwandfrei ... –

3

Dies ist die Lösung NewtonSoft Json zu verwenden.Net (für Leistung) Ich habe einen Teil der Lösung gefunden here und auf 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(); 
     } 
    } 

So dass in meinem Controller, kann ich die

 return new JsonNetResult(result); 

In meinem Modell, kann ich jetzt habe :

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

Beachten Sie, dass jetzt, können Sie die JsonPropertyAttribute zu jeder Eigenschaft müssen Sie serialisieren möchten.

+0

danke eine Million –

Verwandte Themen