So deserialisieren Sie ein JObject in ein .NET-Objekt

240

Ich benutze gerne die Newtonsoft JSON-Bibliothek . Zum Beispiel würde ich ein JObjectaus einem .NET-Objekt erstellen , in diesem Fall eine Instanz von Exception (möglicherweise eine Unterklasse oder nicht).

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

Jetzt weiß ich, dass die Bibliothek JSON-Text (dh eine Zeichenfolge) für ein Objekt deserialisieren kann

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

aber was ich suche ist:

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

Nun, es ist klar, dass ich von JObjectzurück zu JSON-Text wechseln und dann die Deserialisierungsfunktion verwenden kann, aber das scheint mir rückwärts zu sein.

Sebastian
quelle

Antworten:

489

Laut diesem Beitrag ist es jetzt viel besser:

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

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

Dokumentation: Konvertieren Sie JSON in einen Typ

Tien Do.
quelle
10
Irgendwelche Ideen zu den Auswirkungen auf die Leistung hier? Wird jedes Mal Reflexion verwendet?
Shaun Rowan
1
Ist dies mit einem benutzerdefinierten JsonConverter möglich?
Justin Skiles
3
Danke für den Hinweis. Es hat mir sehr geholfen. Lassen Sie mich etwas hinzufügen: In einer generischen Methode, in der ich type verwende T, benötigte ich etwas result=(value is JObject) ? ((JObject)value).ToObject<T>() : (T)default(T);, um es erfolgreich zu konvertieren (Hinweis - valueist ein Objekt, das aus einer Datenbank stammt, die ein JObject sein könnte, oder etwas anderes. In diesem Fall sollte das Ergebnis null sein).
Matt
@ShaunRowan Beim Herumspielen mit Code in Linqpad sieht es so aus, als würde Reflexion verwendet, um die Eigenschaft auf derselben "Ebene" des Zielobjekts wie das entsprechende Feld im JSON-Objekt abzugleichen. Der Name Ihrer Eigenschaft muss mit dem Namen des JSON-Felds übereinstimmen, und der Typ Ihrer Eigenschaft muss ein kompatibler Typ sein.
BobbyA
und verwenden jobject.ToObject(myObject.GetType())Sie, wenn Sie den Objekttyp nicht kennen.
Tohid
45

Aus der Dokumentation habe ich dies gefunden

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

Die Klassendefinition für Personsollte mit folgenden Komponenten kompatibel sein:

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

Bearbeiten

Wenn Sie eine neuere Version von JSON.net verwenden und keine benutzerdefinierte Serialisierung benötigen, lesen Sie bitte die Antwort von TienDo oben (oder unten, wenn Sie mich positiv bewerten: P), die präziser ist.

Sebastian
quelle
2
Ich musste diesen Ansatz anstelle der Kurzform verwenden, um benutzerdefinierte Serialisierungseinstellungen übergeben zu können.
Justin Caldicott
Genau ans ich suche
Mark-VII
2

Zu spät, nur für den Fall, dass jemand nach einem anderen Weg sucht:

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; }
}
Ivan Lopez
quelle
Dies sieht genauso aus wie die akzeptierte Antwort .
Jpaugh