2012-12-01 15 views
12

Desidero sostituire la serializzazione JSON WCF predefinita (per tutti i tipi di dati) con JSON.NET. Ho cercato su tutta la rete e non sono riuscito a trovare una soluzione funzionante.Sostituire serializzatore JSON predefinito in WCF 4 in JSON.NET

Questo è il mio oggetto:

[JsonObject] 
public class TestObject 
{ 
    [JsonProperty("JsonNetName")] 
    public string Name = "John"; 

    [JsonProperty] 
    public DateTime Date = DateTime.Now; 
} 

Questa è la mia funzione di WCF:

[OperationContract] 
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] 
    List<TestObject> Get(); 

Questo è il codice in Global.asax:

 protected void Application_Start(object sender, EventArgs e) 
    { 
     // Create Json.Net formatter serializing DateTime using the ISO 8601 format 
     var serializerSettings = new JsonSerializerSettings(); 

     serializerSettings.Converters.Add(new IsoDateTimeConverter()); 
     serializerSettings.Converters.Add(new BinaryConverter()); 
     serializerSettings.Converters.Add(new JavaScriptDateTimeConverter()); 
     serializerSettings.Converters.Add(new BinaryConverter()); 
     serializerSettings.Converters.Add(new StringEnumConverter()); 

     var config = HttpHostConfiguration.Create().Configuration; 

     Microsoft.ApplicationServer.Http.JsonMediaTypeFormatter jsonFormatter = config.OperationHandlerFactory.Formatters.JsonFormatter; 

     config.OperationHandlerFactory.Formatters.Remove(jsonFormatter); 

     config.OperationHandlerFactory.Formatters.Insert(0, new JsonNetMediaTypeFormatter(serializerSettings)); 

     var httpServiceFactory = new HttpServiceHostFactory 
     { 
      OperationHandlerFactory = config.OperationHandlerFactory, 
      MessageHandlerFactory = config.MessageHandlerFactory 
     }; 

     //Routing 
     RouteTable.Routes.Add(
      new ServiceRoute(
       "Brands", httpServiceFactory, 
       typeof(Brands))); 

     } 

Questo è Web.Config :

<endpointBehaviors> 
    <behavior name="Behavior_Brands"> 
     <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Bare" /> 
    </behavior> 
    </endpointBehaviors> 

e la sezione servizi:

<service name="TestApp.CoreWCF.Brands"> 
    <endpoint address="" behaviorConfiguration="Behavior_Brands" binding="webHttpBinding" contract="TestApp.CoreWCF.IBrands"> 
     <identity> 
     <dns value="localhost" /> 
     </identity> 
    </endpoint> 
    </service> 

E, infine, questo è quello che sto ricevendo al momento del lancio l'URL:

"http://localhost:30000/Brands/Get"

[{"Date":"\/Date(1354364412708+0200)\/","Name":"John"}, {"Date":"\/Date(1354364412708+0200)\/","Name":"John"}] 

La risposta JSON ignora ovviamente la Attributi JSON.NET.

risposta

16

In ogni caso, ho trovato un modo per utilizzare un serializzatore diverso, manualmente, sembra più efficiente e più veloce perché non passa attraverso il serializzatore di Microsoft, sebbene il codice sia un po 'più disordinato.

  1. Impostare tutti i tipi di ritorno come "System.ServiceModel.Channels.Message" nelle interfacce e classi per la loro applicazione.

    [OperationContract] 
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] 
    System.ServiceModel.Channels.Message GetData(); 
    
  2. Creare un metodo di estensione in modo che si potrebbe facilmente costruire un flusso di memoria di un oggetto, utilizzando il serializzatore JSON.NET (o seconda di quale si desidera utilizzare).

    public static System.ServiceModel.Channels.Message GetJsonStream(this object obj) 
    { 
        //Serialize JSON.NET 
        string jsonSerialized = JsonConvert.SerializeObject(obj); 
    
        //Create memory stream 
        MemoryStream memoryStream = new MemoryStream(new UTF8Encoding().GetBytes(jsonSerialized)); 
    
        //Set position to 0 
        memoryStream.Position = 0; 
    
        //return Message 
        return WebOperationContext.Current.CreateStreamResponse(memoryStream, "application/json"); 
    } 
    
  3. Nel corpo del metodo, restituire l'oggetto serializzato direttamente nel flusso

    return yourObject.GetJsonStream(); 
    
+4

Quali sono i risultati dei test indicano che v'è sicuramente più veloce? Sfortunatamente per il mio caso di test (gerarchia di oggetti 500KB) utilizzando tecniche alternative simili, sembra che il doppio passo della serializzazione JSON.NET _plus_ byte array che copia su UTF8 lo rende in qualche modo più costoso di un semplice DataContractJsonSerializer. :-( – icelava

Problemi correlati