2011-12-12 9 views
6

Sono di fronte a un problema di serializzazione di un oggetto in JSON per abbinare il nome parametro della chiamata di funzione WCF. Il problema è di mappare il nome del parametro, cioè la stringa JSON in entrata dovrebbe avere il valore iniziale come lo stesso nome del parametro passato nella funzione, ad es.Serializzazione della stringa JSON per la corrispondenza con il servizio WCF Funzione Parametro

"{\"GetComplexDataResult\":{\"BoolValue\":true,\"StringValue\":\"Hello World!\"}}" 

Questa è la mia funzione WCF che io chiamo nel mio cliente e, come si può vedere il nome del parametro è uguale a quella che viene restituito "GetComplexDataResult"

[OperationContract] 
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] 
String SaveData(CompositeType GetComplexDataResult); 

Il problema che si verifica è quando provo a serializzare il mio oggetto usando Microsoft System.Web.Script.Serialization.JavaScriptSerializer o qualsiasi altra libreria (es. Json.NET)

mi restituisce solo {\"BoolValue\":true,\"StringValue\":\"Hello World!\"} anche se passo un oggetto della stessa classe "CompositeType" (Questo è il codice lato client) per esempio

CompositeType GetComplexDataResult= new CompositeType(); 
GetComplexDataResult.BoolValue = true; 
GetComplexDataResult.StringValue = "Hello World"; 

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
string json = serializer.Serialize(patchVersion); 

mia domanda è come posso ottenere questa stringa JSON

"{\"GetComplexDataResult\":{\"BoolValue\":true,\"StringValue\":\"Hello World!\"}}" 

Invece di

{\"BoolValue\":true,\"StringValue\":\"Hello World!\"} 

con da solo di passaggio il mio oggetto JSON parser. Posso concatenarlo manualmente dopo aver generato la mia stringa JSON, ma ciò richiederebbe troppo tempo per il lavoro. C'è un parser che risolve questo problema.

risposta

3

Se serializzi un oggetto anonimo utilizzando il nome parametro come nome di una proprietà, lo includerà nella stringa json. Prova questo:

string json = serializer.Serialize(new { GetComplexDataResult = patchVersion}); 

Inoltre, se non si cura se il nome del parametro è incluso nel JSON a tutti, è possibile impostare il BodyStyle-BodyStyle = WebMessageBodyStyle.Bare.

+0

Grazie mille alla deriva questo ha funzionato per me. – adnangohar

1

Per ogni parser JSON che ho visto, il tipo di oggetto non è mai incluso nel JSON. La serializzazione rappresenta un'istanza di quell'oggetto. Sarebbe meglio aggiungere un attributo type se è necessario conoscere il riferimento al tipo di origine dell'oggetto. {\"BoolValue\":true,\"StringValue\":\"Hello World!\",\"type\":\"GetComplexDataResult\"}.

L'output mi ricorda in modo impercettibile una busta SOAP. Non hai bisogno dell'incapsulamento - lo rende solo più complesso. JSON è semplice: tienilo semplice.

+0

Il problema qui non riguarda il tipo relativo all'aggiunta del nome dell'oggetto "GetComplexDataResult" all'inizio del JSON generato. I nomi delle mappe WCF dalla stringa JSON e i parametri passati per funzionare. La risposta JSON di WCF è simile a "{\" GetComplexDataResult \ ": {\" BoolValue \ ": true, \" StringValue \ ": \" Hello World! \ "}}" E come sto chiamando una funzione utilizzando GET it aggiunge automaticamente il nome della funzione "GetComplexData" e l'attributo extra "Result" ad esso. Quindi, stavo pensando che ci potrebbe essere un modo per fare ciò come sta facendo WCF, quindi deve essere possibile. – adnangohar

2

La mia domanda è, c'è un motivo significativo per cui è necessario avere \"GetComplexDataResult\" all'inizio dei dati JSON?

Non credo che i serializzatori JSON faranno quello che vuoi loro in modo nativo, devi praticamente gestirlo da solo.

Quello che facciamo in azienda per cui lavoro, è costruire il nostro wrapper di risposta che rende tutte le nostre risposte lo stesso formato per tutti i nostri servizi JSON. Così praticamente realizziamo un datacontract standard che restituisce un datacontract per una delle proprietà del wrapper outter. Potresti fare qualcosa del genere per ottenere la funzionalità di "annidamento" che stai cercando.

Ecco un esempio:

[DataContract] 
    public class ServiceResult<T> 
    { 
     [DataMember] 
     public T GetComplexDataResult{ get; set; } 
    } 

UPDATE: Modificato questo per essere generico. volevo spiegare ulteriormente dove stavo andando con la mia risposta originale. Anche in questo caso, la risposta adrift è più concisa, tieni a mente solo se vuoi espandere, ad esempio aggiungi messaggi, dovresti fare qualcosa di simile, o farlo manualmente da solo. Mi piace molto questo approccio perché so quale sarà il mio formato sempre uguale, indipendentemente dai servizi WCF che chiamo.

+0

Sì, come i nomi delle mappe WCF nella stringa JSON ai parametri passati alle funzioni, ad es. String SaveData (CompositeType GetComplexDataResult) ha un parametro denominato "GetComplexDataResult" e per mappare il valore su questo oggetto la stringa JSON deve essere "{\" GetComplexDataResult \ ": {\" BoolValue \ ": true, \" StringValue \ ": \" Ciao mondo!\"}}". Ho bisogno di vedere quanto la creazione di un wrapper attorno ai miei oggetti possa aiutarmi. – adnangohar

+0

Faccio esattamente la stessa cosa che vuoi, come ho notato, ma lo avvolgiamo in un generico contratto ServiceResult in cui la proprietà interna è pubblica T [] Data {get; impostato; }. Quindi i dati restituiti sono sempre nel "Data" restituito a json. La risposta alla deriva essenzialmente fa la stessa identica cosa, ottieni lo stesso risultato. – Etch

Problemi correlati