2013-05-23 13 views
8

Non ho mai usato l'API Web prima, ma ho bisogno di un servizio web che accetti/restituisca oggetti JSON e l'utilizzo di questo mi è sembrato una cosa ragionevole. Sembrava abbastanza semplice (se non un po 'eccessivo per i miei scopi), ma una struttura di dati che ho bisogno di trattare con simile a:Come posso utilizzare una parola chiave riservata come identificativo nella mia classe di modello JSON?

{ 
    "values":["foo", "bar"], 
    "default":"bar" 
} 

E così sono andato a fare un oggetto Modello:

class DropDownValues { 
    public string[] values { get; set; } 
    public string default { get; set; } 
} 

Il problema è che il valore predefinito sembra essere una parola chiave protetta. Ci deve essere un modo per aggirare questo, giusto?

+0

si può provare questa 'stringa pubblica selezionata {get; impostato; } ' – Sender

risposta

8

Suggerirei di andare in modo diverso. Mantieni il tuo modello di oggetto C# il più standard possibile (non utilizzerei il segno @ e C# keywords come nome proprietà).

Possiamo separare il mondo serializzato (JSON) e gli oggetti C#, semplicemente utilizzando le funzionalità di Json.NET.

Uno dei più semplice da usare è decorazione con attributo:

[JsonProperty(PropertyName = "default")] 
public string DefaultValue { get; set; } 

In questo caso dobbiamo fare riferimento Newtonsoft.Json nel progetto. Se deve essere POCO, possiamo introdurre CustomResolver derrived da DefaultContractResolver e definiamo queste conversioni lì ...

Ma la separazione di preoccupazione in questo caso è un po 'la soluzione più puro, direi

EDIT: JSON contratto Resolver progetto(vedi commenti)

Nota importante: Newtonsoft.Json fa parte delle API Web. Non solo è un open source, ma anche il team di MS punta su questo come serializer JSON di base.

1) Newtonsoft.Json (come parte di Web.API) è già installato nella soluzione. Quindi non devi scaricare (nuget) separatamente. Sarebbe sempre nella tua cartella packages. Quindi, per usare l'attributo è sufficiente aggiungere il riferimento. È qui...

2) C'è una piccola bozza su come fare per gli attributi, mantenendo il POCO. Come ho cercato di spiegare qui: POCO's, behavior and Peristance Igorance, per mantenere POCO (ad esempio, sfruttiamo l'architettura a strati con NHibernate su un livello dati), possiamo sostituire gli attributi con un Contract Resolver. La nostra biblioteca POCO non deve fare riferimento a qualcosa di

Non ci resta che fare estendere il livello di servizio:

public class MyResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(
     MemberInfo member, 
     MemberSerialization memberSerialization) 
    { 

     var jProperty = base.CreateProperty(member, memberSerialization); 

     var propertyInfo = member as PropertyInfo; 
     if (propertyInfo == null) 
     { 
      return jProperty; 
     } 

     // just adjust in case if Property name is DefaultValue 
     var isDefaultValueProeprty = 
        propertyInfo.Name.Equals("DefaultValue"); 

     if(isDefaultValueProeprty) 
     { 
      jProperty.PropertyName = "default"; 
     } 

     return jProperty; 
    } 
    ... 

In questo modo abbiamo fornito le stesse informazioni a serailizer come con il [JsonPropertyAttribute].

Ora, dobbiamo solo usarlo. Ci sono molti modi (ad esempio globale) ma possiamo farlo solo per un controller:

protected override void Initialize(HttpControllerContext context) 
{ 
    base.Initialize(context); 

    var jSettings = context.Configuration.Formatters.JsonFormatter.SerializerSettings; 
    jSettings.ContractResolver = MyResolver; 
} 
+0

Mi piace questa soluzione, ma sfortunatamente non posso usare Newtonsoft (almeno non senza un sacco di problemi). Puoi espandere un po 'su come usare CustomResolver? –

10

È possibile utilizzare le parole chiave in C# come identificatori anteponendo @ di fronte a esse.

+0

Mah, sei un risparmiatore di vita, questo ha impiegato ore dalla mia vita ... –

3

La classe DropDownValues utilizzando convenzione cammello:

class DropDownValues { 
    public string[] values { get; set; } 
    public string default { get; set; } 
} 

È possibile utilizzare il prefisso @ per Passby ma non è ancora seguente C# codifica convenzione.

La soluzione migliore che è possibile sia evitare la parola chiave riservata e ancora utilizzare C# codifica convenzione sta usando CamelCasePropertyNamesContractResolver:

class DropDownValues { 
    public string[] Values { get; set; } 
    public string Default { get; set; } 
} 

e personalizzare JsonFormatter per evitare disallineamento convenzione tra C# e oggetto JSON, come di seguito:

var jsonFormatter = configuration.Formatters.JsonFormatter; 
jsonFormatter.SerializerSettings = new JsonSerializerSettings() 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver() 
}; 
Problemi correlati