Come deserializzare un oggetto JObject in .NET


241

Uso felicemente la libreria JSON di Newtonsoft . Ad esempio, vorrei creare un JObjectda un oggetto .NET, in questo caso un'istanza di eccezione (potrebbe o non potrebbe essere una sottoclasse)

if (result is Exception)
    var jobjectInstance = JObject.FromObject(result);

ora so che la libreria può deserializzare il testo JSON (cioè una stringa) su un oggetto

// only works for text (string)
Exception exception = JsonConvert.DeserializeObject<Exception>(jsontext); 

ma quello che sto cercando è:

// now i do already have an JObject instance
Exception exception = jobjectInstance.????

Bene, è chiaro che posso tornare JObjectindietro al testo JSON e quindi utilizzare la funzionalità di deserializzazione, ma questo mi sembra arretrato.

Risposte:


489

Secondo questo post , ora è molto meglio:

// pick out one album
JObject jalbum = albums[0] as JObject;

// Copy to a static Album instance
Album album = jalbum.ToObject<Album>();

Documentazione: convertire JSON in un tipo


10
Qualche idea sulle implicazioni delle prestazioni qui? La riflessione verrà utilizzata ogni volta?
Shaun Rowan,

1
È possibile farlo con un JsonConverter personalizzato?
Justin Skiles,

3
Grazie per il suggerimento. Mi ha aiutato molto. Consentitemi di aggiungere qualcosa: in un metodo generico in cui sto usando il tipo T, ho richiesto qualcosa di simile result=(value is JObject) ? ((JObject)value).ToObject<T>() : (T)default(T);per convertirlo correttamente (nota: valueè un oggetto proveniente da un database che potrebbe essere un oggetto JOB o qualcos'altro nel qual caso il risultato dovrebbe essere nullo).
Matt,

@ShaunRowan Giocando con il codice in Linqpad, sembra che la riflessione sia usata per abbinare la proprietà allo stesso "livello" dell'oggetto target del campo corrispondente nell'oggetto JSON. Il nome della proprietà deve corrispondere al nome del campo JSON e il tipo di proprietà deve essere un tipo compatibile.
Bobby,

e utilizzare jobject.ToObject(myObject.GetType())se non si conosce il tipo di oggetto.
Tohid

45

Dalla documentazione ho trovato questo

JObject o = new JObject(
   new JProperty("Name", "John Smith"),
   new JProperty("BirthDate", new DateTime(1983, 3, 20))
);

JsonSerializer serializer = new JsonSerializer();
Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));

Console.WriteLine(p.Name);

La definizione della classe per Persondovrebbe essere compatibile con quanto segue:

class Person {
    public string Name { get; internal set; }
    public DateTime BirthDate { get; internal set; }
}

modificare

Se stai usando una versione recente di JSON.net e non hai bisogno di una serializzazione personalizzata, vedi la risposta di TienDo sopra (o sotto se mi voti: P), che è più concisa.


2
Avevo bisogno di usare questo approccio, piuttosto che la stenografia, per poter passare le impostazioni di serializzazione personalizzate.
Justin Caldicott,

Esatto e io sto cercando
Mark-VII,

2

Troppo tardi, nel caso in cui qualcuno stia cercando un altro modo:

void Main()
{
    string jsonString = @"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}";

    Product product = new Product();
    //Serializing to Object
    Product obj = JObject.Parse(jsonString).SelectToken("$.Manufacturers[?(@.Name == 'Acme Co' && @.Name != 'Contoso')]").ToObject<Product>();

    Console.WriteLine(obj);
}


public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Sembra esattamente la risposta accettata .
jpaugh
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.