Come posso cambiare i nomi delle proprietà durante la serializzazione con Json.net?


434

Ho alcuni dati in un oggetto DataSet C #. Posso serializzarlo adesso usando un convertitore Json.net come questo

DataSet data = new DataSet();
// do some work here to populate 'data'
string output = JsonConvert.SerializeObject(data);

Tuttavia, questo utilizza i nomi delle proprietà da dataquando si stampa sul file .json. Vorrei cambiare i nomi delle proprietà in modo che siano diversi (diciamo, cambia "pippo" in "bar").

Nella documentazione di Json.net , in "Serializzazione e deserializzazione di JSON" → "Attributi di serializzazione", si dice "JsonPropertyAttribute ... consente di personalizzare il nome". Ma non c'è esempio. Qualcuno sa come utilizzare un JsonPropertyAttribute per modificare il nome della proprietà in qualcos'altro?

( Link diretto alla documentazione )

La documentazione di Json.net sembra essere scarsa. Se hai un ottimo esempio, proverò ad aggiungerlo alla documentazione ufficiale. Grazie!


3
Cordiali saluti, c'è un esempio di questo nella documentazione in Esempi -> Serializzazione di JSON -> JsonPropertyAttribute name . Non sono sicuro a che punto è stato aggiunto.
Brian Rogers,

Risposte:


791

Puoi decorare la proprietà che desideri controllandone il nome con l' [JsonProperty]attributo che ti consente di specificare un nome diverso:

using Newtonsoft.Json;
// ...

[JsonProperty(PropertyName = "FooBar")]
public string Foo { get; set; }

Documentazione: attributi di serializzazione


1
Ciò richiede che legga i miei dati in un oggetto personalizzato che creo anziché in un DataSet?
Culix del

3
@culix, sì, richiede l'utilizzo di un modello. Un DataSet è una struttura debolmente tipizzata, quindi parlare di nomi di proprietà non è molto logico.
Darin Dimitrov,

76
Come scorciatoia, puoi anche fare[JsonProperty("FooBar")]
Bart Verkoeijen il

2
@DarinDimitrov c'è un modo per farlo senza Json .NET?
CH81

12
L'uso di un modello è semplice, basta prendere un campione del proprio JSON e incollarlo in un file .cs vuoto usando "Incolla speciale" -> "Incolla JSON come classi". - È integrato in Visual Studio. - Da lì, in pratica, devi solo impostare le cose come titoli case / rinomina cose per usare le convenzioni di denominazione .NET, ecc. (Usando un convertitore di case titolo per il primo e l'attributo JsonProperty per il secondo).
BrainSlugs83

71

Se non si ha accesso alle classi per modificare le proprietà o non si desidera utilizzare sempre la stessa proprietà di ridenominazione, è possibile anche rinominare creando un resolver personalizzato.

Ad esempio, se hai una classe chiamata MyCustomObject, che ha una proprietà chiamata LongPropertyName, puoi usare un risolutore personalizzato come questo ...

public class CustomDataContractResolver : DefaultContractResolver
{
  public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver ();

  protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
  {
    var property = base.CreateProperty(member, memberSerialization);
    if (property.DeclaringType == typeof(MyCustomObject))
    {
      if (property.PropertyName.Equals("LongPropertyName", StringComparison.OrdinalIgnoreCase))
      {
        property.PropertyName = "Short";
      }
    }
    return property;
  }
}

Quindi chiamare per la serializzazione e fornire il resolver:

 var result = JsonConvert.SerializeObject(myCustomObjectInstance,
                new JsonSerializerSettings { ContractResolver = CustomDataContractResolver.Instance });

E il risultato sarà abbreviato in {"Short": "valore prop"} invece di {"LongPropertyName": "valore prop"}

Maggiori informazioni sui resolver personalizzati qui


1
Questa è una soluzione migliore se la classe da serializzare viene dichiarata in un altro assembly che include una versione diversa del pacchetto Newtonsoft.Json. (potrebbe anche non generare alcun errore). Il DefaultContractResolverdevono essere messi nello stesso assieme in cui viene applicato il metodo JsonConvert.Serialize ().
Artemious

6

C'è ancora un altro modo per farlo, che sta usando una particolare NamingStrategy , che può essere applicata a una classe o una proprietà decorandole con [JSonObject]o [JsonProperty].

Esistono strategie di denominazione predefinite come CamelCaseNamingStrategy, ma puoi implementare le tue.

L'implementazione di diverse strategie di denominazione è disponibile qui: https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization


3
Se sei in grado, condividi un esempio di implementazione personalizzata di NamingStrategy
user1007074

Ovviamente no. Avresti dovuto farlo da solo, ma ti risparmierò il tempo di dirti che devi semplicemente ereditare newtonsoft.com/json/help/html/… Puoi vedere l'implementazione delle classi esistenti e crearne una tua.
JotaBe,

Grazie - avrei dovuto aggiornare il mio commento: infatti, grazie alla gloria di GitHub, si può usare una delle implementazioni di Newtonsoft come esempio, diciamo, questa
user1007074

8
@JotaBe, questo non è lo spirito di StackOverflow. E come programmatore che vuole solo fare il mio lavoro, francamente, sarebbe stato mille volte meglio per me sollevare il codice che potresti aver fornito. E avresti ottenuto anche il mio voto. Ho 18 anni di esperienza nella programmazione e sono classificato da TripleByte come "esperto" in c #. Non OGNI problema deve essere lasciato come un "esercizio per il lettore". A volte vogliamo solo fare il nostro lavoro e andare avanti.
bboyle1234

2
Sono d'accordo con te e di solito non scrivo questo tipo di commento. Tuttavia, posso assicurare che, in questo caso, guardare il codice collegato è molto meglio di qualsiasi spiegazione che posso dare. E json.net è una libreria open source molto ben documentata. Collegamento incluso alle implementazioni (esempi perfetti)
JotaBe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.