Korzystanie Z JsonConvert.DeserializeObject do deserializacji Json do klasy C# POCO

Oto moja prostaUser klasa POCO:

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

}

I metoda, której używam do deserializacji odpowiedzi JSON do obiektu User (to rzeczywiste wywołanie JSON jest tutaj):

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

Wywołanie wyjątku:

Nie można deserializować bieżącego obiektu JSON (np. {"name": "value"}) do typu "System.Kolekcje.Ogólne.Lista " 1[CoderwallDotNet.Api.Modelki.Konto]" ponieważ typ wymaga tablicy JSON (np. [1,2,3]) do deserializacji prawidłowo.

Aby naprawić ten błąd, Zmień JSON na tablicę JSON (np. [1,2,3]) lub zmienić deserializowany Typ tak, aby był normalnym Typu. NET (np. nie prymitywny typ jak integer, Nie zbiór typu jak tablica lub Lista), które mogą być deserializowane z JSON obiekt. JsonObjectAttribute można również dodać do typu, aby go wymusić deserializacji z obiektu JSON. / Align = "left" / github", linia 1, pozycja 129.

Nigdy nie pracowałem z tym DeserializeObject metoda wcześniej, utknąłem tutaj.

Upewniłem się, że nazwy właściwości w klasie POCO są takie same jak nazwy w odpowiedzi JSON.

Co mogę spróbować deserializować JSON do tej klasy POCO?

Author: Only Bolivian Here, 2012-06-20

7 answers

Oto działający przykład.

Punkty kluczowe to:

  • Deklaracja Accounts
  • użycie atrybutu JsonProperty

.

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;
}
 80
Author: L.B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 20:12:34

Można utworzyć JsonConverter. Zobacz Tutaj aby uzyskać przykład podobny do twojego pytania.

 4
Author: SwDevMan81,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:32

Innym i bardziej usprawnionym podejściem do deserializacji łańcucha JSON z obudową wielbłąda do obiektu poco z obudową Pascala jest użycie CamelCasePropertyNamesContractResolver.

To część Newtonsoftu.Json.Przestrzeń nazw serializacji. Takie podejście zakłada, że jedyna różnica między obiektem JSON a POCO leży w obudowie nazw właściwości. Jeśli nazwy właściwości są pisane inaczej, musisz użyć atrybutów JsonProperty do mapowania nazwy nieruchomości.
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
Author: John Iwasz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-19 22:05:46

Właściwość konta jest zdefiniowana następująco:

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

Twój POCO stwierdza to:

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

Spróbuj użyć tego Json:

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

Tablica elementów (które będą mapowane do listy) jest zawsze zamknięta w nawiasach kwadratowych.

Edit: konto Poco będzie coś takiego:

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

I może inne właściwości.

Edit 2: aby nie mieć tablicy użyj właściwości w następujący sposób:

public Account Accounts { get; set; }

Z czymś takim jak próbka zajęcia, które zamieściłem w pierwszej edycji.

 3
Author: Sascha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 18:59:41
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.`

Cała wiadomość wskazuje, że możliwe jest serializowanie do obiektu List, ale wejście musi być listą JSON. Oznacza to, że Twój JSON musi zawierać

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

Gdzie dane AccountObject to JSON reprezentujący obiekt Account lub obiekt Badge

Wydaje się, że obecnie jest to

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

Gdzie accounts jest obiektem JSON (oznaczonym nawiasami klamrowymi), a nie tablicą obiektów JSON (tablice są oznaczone nawiasami), co jest tym, czego chcesz. Try

"accounts" : [{"github":"sergiotapia"}]
 2
Author: dmi_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 19:09:03

Zgodnie z przyjętą odpowiedzią, jeśli masz próbkę tekstu JSON, możesz ją podłączyć do tego konwertera , wybrać opcje i wygenerować kod C#.

Jeśli nie znasz typu w czasie wykonywania, ten temat wygląda jakby pasował.

Dynamicznie deserializuj json do dowolnego obiektu przekazanego. c #

 1
Author: Jim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:04

Nie o to mi chodziło. Co zrobić, jeśli masz typ generyczny, który jest znany tylko w czasie wykonywania?

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
Author: Latency,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 18:41:48