it-swarm.com.de

JsonConvert.DeserializeObject zum Deserialisieren von Json in eine C # POCO-Klasse verwenden

Hier ist meine einfache User POCO-Klasse:

/// <summary>
/// The User class represents a Coderwall User.
/// </summary>
public class User
{
    /// <summary>
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
    /// </summary>
    public string Username { get; set; }

    /// <summary>
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// A User's location. eh: "Bolivia, USA, France, Italy"
    /// </summary>
    public string Location { get; set; }

    public int Endorsements { get; set; } //Todo.
    public string Team { get; set; } //Todo.

    /// <summary>
    /// A collection of the User's linked accounts.
    /// </summary>
    public List<Account> Accounts { get; set; }

    /// <summary>
    /// A collection of the User's awarded badges.
    /// </summary>
    public List<Badge> Badges { get; set; }

}

Und die Methode, die ich verwende, um eine JSON-Antwort in ein User-Objekt zu deserialisieren (dieser tatsächliche JSON-Aufruf ist hier ):

private User LoadUserFromJson(string response)
{
    var outObject = JsonConvert.DeserializeObject<User>(response);
    return outObject;
}

Dies löst eine Ausnahme aus:

Das aktuelle JSON-Objekt kann nicht deserialisiert werden (z. B. {"name": "value"}) in den Typ 'System.Collections.Generic.List`1 [CoderwallDotNet.Api.Models.Account]' weil der Typ ein JSON-Array (z. B. [1,2,3]) zum Deserialisieren von .__ erfordert. korrekt. 

Um diesen Fehler zu beheben, ändern Sie entweder den JSON in ein JSON-Array (z. B. [1,2,3]) oder ändern Sie den deserialisierten Typ, sodass es normal ist. .NET-Typ (z. B. kein primitiver Typ wie Integer, keine Sammlung Typ wie ein Array oder eine Liste), der von einem JSON-Code deserialisiert werden kann Objekt. JsonObjectAttribute kann auch zum Typ hinzugefügt werden, um es zu erzwingen aus einem JSON-Objekt deserialisieren. Pfad 'accounts.github', Zeile 1, Position 129.

Da ich noch nie mit dieser DeserializeObject-Methode gearbeitet habe, bin ich irgendwie hier festgefahren.

Ich habe sichergestellt, dass die Eigenschaftsnamen in der POCO-Klasse mit den Namen in der JSON-Antwort übereinstimmen. 

Was kann ich versuchen, JSON in diese POCO-Klasse zu deserialisieren?

51

Hier ist ein Arbeitsbeispiel. 

Schlüsselpunkte sind:

  • Deklaration von Accounts
  • Verwendung des JsonProperty-Attributs

.

using (WebClient wc = new WebClient())
{
    var json = wc.DownloadString("http://coderwall.com/mdeiters.json");
    var user = JsonConvert.DeserializeObject<User>(json);
}

-

public class User
{
    /// <summary>
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
    /// </summary>
    [JsonProperty("username")]
    public string Username { get; set; }

    /// <summary>
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
    /// </summary>
    [JsonProperty("name")]
    public string Name { get; set; }

    /// <summary>
    /// A User's location. eh: "Bolivia, USA, France, Italy"
    /// </summary>
    [JsonProperty("location")]
    public string Location { get; set; }

    [JsonProperty("endorsements")]
    public int Endorsements { get; set; } //Todo.

    [JsonProperty("team")]
    public string Team { get; set; } //Todo.

    /// <summary>
    /// A collection of the User's linked accounts.
    /// </summary>
    [JsonProperty("accounts")]
    public Account Accounts { get; set; }

    /// <summary>
    /// A collection of the User's awarded badges.
    /// </summary>
    [JsonProperty("badges")]
    public List<Badge> Badges { get; set; }
}

public class Account
{
    public string github;
}

public class Badge
{
    [JsonProperty("name")]
    public string Name;
    [JsonProperty("description")]
    public string Description;
    [JsonProperty("created")]
    public string Created;
    [JsonProperty("badge")]
    public string BadgeUrl;
}
85
L.B

Ein weiterer und strengerer Ansatz zur Deserialisierung einer Kamel-JSON-Zeichenfolge in ein Pascal-Cased-Objekt ist die Verwendung von CamelCasePropertyNamesContractResolver

Es ist Teil des Namensraums Newtonsoft.Json.Serialization. Bei diesem Ansatz wird davon ausgegangen, dass der einzige Unterschied zwischen dem JSON-Objekt und dem POCO im Gehäuse der Eigenschaftsnamen liegt. Wenn die Eigenschaftsnamen unterschiedlich geschrieben sind, müssen Sie die JsonProperty-Attribute zum Zuordnen der Eigenschaftsnamen verwenden.

using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization;

. . .

private User LoadUserFromJson(string response) 
{
    JsonSerializerSettings serSettings = new JsonSerializerSettings();
    serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    User outObject = JsonConvert.DeserializeObject<User>(jsonValue, serSettings);

    return outObject; 
}
4
John Iwasz

Sie könnten eine JsonConverter erstellen. Siehe hier für ein Beispiel, das Ihrer Frage ähnlich ist.

4
SwDevMan81

Die Kontoeigenschaft ist folgendermaßen definiert:

"accounts":{"github":"sergiotapia"}

Ihr POCO sagt dies aus:

public List<Account> Accounts { get; set; }

Versuchen Sie es mit diesem Json:

"accounts":[{"github":"sergiotapia"}]

Ein Array von Elementen (die der Liste zugeordnet werden sollen) ist immer in eckigen Klammern angegeben.

Bearbeiten: Der Account Poco sieht ungefähr so ​​aus:

class Account {
    public string github { get; set; }
}

und vielleicht andere Eigenschaften.

Edit 2: Um kein Array zu haben, benutze die Eigenschaft wie folgt:

public Account Accounts { get; set; }

mit so etwas wie der Beispielklasse, die ich in der ersten Bearbeitung gepostet habe.

3
Sascha
to fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the
deserialized type so that it is a normal .NET type (e.g. not a primitive type like
integer, not a collection type like an array or List) that can be deserialized from a
JSON object.`

Die gesamte Nachricht zeigt an, dass es möglich ist, zu einem List-Objekt zu serialisieren, die Eingabe muss jedoch eine JSON-Liste sein. Dies bedeutet, dass Ihr JSON enthalten muss

"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],

Hierbei handelt es sich bei AccountObject-Daten um JSON, die Ihr Account-Objekt oder Ihr Badge-Objekt darstellen

Was es momentan scheint, ist

"accounts":{"github":"sergiotapia"}

Wenn Konten ein JSON-Objekt sind (durch geschweifte Klammern gekennzeichnet), nicht ein Array von JSON-Objekten (Arrays werden durch Klammern gekennzeichnet), was Sie möchten. Versuchen

"accounts" : [{"github":"sergiotapia"}]
2
dmi_

Im Sinne der akzeptierten Antwort können Sie, wenn Sie ein JSON-Textbeispiel haben, diese an this converter anschließen, Ihre Optionen auswählen und den C # -Code generieren.

Wenn Sie den Typ zur Laufzeit nicht kennen, sieht dieses Thema so aus, als würde es passen.

dynamisch deserialisieren Sie json in ein beliebiges Objekt. c #

1
Jim

Daran habe ich nicht gedacht. Was tun Sie, wenn Sie einen generischen Typ haben, der nur zur Laufzeit bekannt ist?

public MyDTO toObject() {
  try {
    var methodInfo = MethodBase.GetCurrentMethod();
    if (methodInfo.DeclaringType != null) {
      var fullName = methodInfo.DeclaringType.FullName + "." + this.dtoName;
      Type type = Type.GetType(fullName);
      if (type != null) {
        var obj = JsonConvert.DeserializeObject(payload);
      //var obj = JsonConvert.DeserializeObject<type.MemberType.GetType()>(payload);  // <--- type ?????
          ...
      }
    }

    // Example for Java..   Convert this to C#
    return JSONUtil.fromJSON(payload, Class.forName(dtoName, false, getClass().getClassLoader()));
  } catch (Exception ex) {
    throw new ReflectInsightException(MethodBase.GetCurrentMethod().Name, ex);
  }
}
0
Latency