Jak deserializować obiekt JObject do obiektu .NET


241

Z przyjemnością korzystam z biblioteki JSON firmy Newtonsoft . Na przykład utworzyłbym JObjectz obiektu .NET, w tym przypadku wystąpienie wyjątku (może, ale nie musi być podklasą)

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

teraz wiem, że biblioteka może przekształcić obiekt JSON w tekst (tj. ciąg) do obiektu

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

ale szukam:

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

Cóż, jasne jest, że mogę przejść z JObjectpowrotem do tekstu JSON, a następnie użyć funkcji deserializacji, ale wydaje mi się to odwrotnie.

Odpowiedzi:


489

Według tego postu jest teraz znacznie lepiej:

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

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

Dokumentacja: Konwertuj JSON na typ


10
Jakieś pomysły na wpływ na wydajność? Czy odbicie będzie wykorzystywane za każdym razem?
Shaun Rowan

1
Czy można to zrobić za pomocą niestandardowego konwertera JsonConverter?
Justin Skiles

3
Dziękuję za podpowiedź. Bardzo mi pomogło. Pozwól, że coś dodam: w ogólnej metodzie, w której używam typu T, potrzebowałem czegoś takiego, jak result=(value is JObject) ? ((JObject)value).ToObject<T>() : (T)default(T);jego pomyślna konwersja (uwaga - valueto obiekt pochodzący z bazy danych, który może być JObject lub coś innego, w którym to przypadku wynik powinien być zerowy).
Matt

@ShaunRowan Bawiąc się kodem w Linqpad, wygląda na to, że odbicie jest używane do dopasowania właściwości na tym samym „poziomie” obiektu docelowego, co odpowiednie pole w obiekcie JSON. Nazwa twojej właściwości musi być zgodna z nazwą pola JSON, a typ twojej właściwości musi być zgodnym typem.
BobbyA

i użyj, jobject.ToObject(myObject.GetType())jeśli nie znasz typu obiektu.
Tohid

45

Z dokumentacji znalazłem to

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);

Definicja klasy Personpowinna być zgodna z następującymi:

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

Edytować

Jeśli używasz najnowszej wersji JSON.net i nie potrzebujesz niestandardowej serializacji, zapoznaj się z odpowiedzią TienDo powyżej (lub poniżej, jeśli głosujesz: P), która jest bardziej zwięzła.


2
Musiałem użyć tego podejścia, a nie stenografii, aby móc przekazać niestandardowe ustawienia serializacji.
Justin Caldicott,

Dokładnie ans szukam
Mark-VII

2

Za późno, na wypadek, gdyby ktoś szukał innego sposobu:

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; }
}

To wygląda dokładnie tak, jak zaakceptowana odpowiedź .
jpaugh
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.