32 votes

Désérialisation de JSON vers 2 modèles différents

La bibliothèque Newtonsoft.JSON a-t-elle un moyen simple de désérialiser automatiquement JSON en 2 modèles/classes différents ?

Par exemple, je reçois le JSON :

[{
  "guardian_id": "1453",
  "guardian_name": "Foo Bar",
  "patient_id": "938",
  "patient_name": "Foo Bar",
}]

Et j'ai besoin de désérialiser cela vers les modèles suivants :

class Guardian {

  [JsonProperty(PropertyName = "guardian_id")]
  public int ID { get; set; }

  [JsonProperty(PropertyName = "guardian_name")]
  public int Name { get; set; }
}

class Patient {

  [JsonProperty(PropertyName = "patient_id")]
  public int ID { get; set; }

  [JsonProperty(PropertyName = "patient_name")]
  public int Name { get; set; }
}

Existe-t-il un moyen simple de désérialiser ce JSON en 2 modèles sans avoir à itérer sur le JSON ? Peut-être que les identifiants de propriété JSON feront l'affaire ?

Pair<Guardian, Patient> pair = JsonConvert.DeserializeObject(response.Content);

27voto

Nisarg Points 11215

Tout d'abord, vos modèles sont légèrement incorrects. Les propriétés du nom doivent être des chaînes de caractères, au lieu d'entiers :

class Guardian
{

    [JsonProperty(PropertyName = "guardian_id")]
    public int ID { get; set; }

    [JsonProperty(PropertyName = "guardian_name")]
    public string Name { get; set; }            // <-- This
}

class Patient
{

    [JsonProperty(PropertyName = "patient_id")]
    public int ID { get; set; }

    [JsonProperty(PropertyName = "patient_name")]
    public string Name { get; set; }            // <-- This
}

Une fois que vous avez corrigé cela, vous pouvez désérialiser la chaîne JSON en deux listes de types différents. Dans votre cas, List<Guardian> y List<Patient> respectivement :

string json = @"[{'guardian_id':'1453','guardian_name':'Foo Bar','patient_id':'938','patient_name':'Foo Bar'}]";
var guardians = JsonConvert.DeserializeObject<List<Guardian>>(json);
var patients = JsonConvert.DeserializeObject<List<Patient>>(json);

10voto

Peter B Points 69

Si vous voulez le faire en un seul appel, vous devez créer une classe qui correspond au JSON. Cette classe peut alors renvoyer Guardian y Patient les objets, si nécessaire. Vous devrez également utiliser un tableau ou une liste pour le type de retour car la fonction source JSON est un tableau.

La classe à créer :

public class Pair
{
    public Pair()
    {
        Guardian = new Guardian();
        Patient = new Patient();
    }

    [JsonIgnore]
    public Guardian Guardian { get; set; }

    [JsonIgnore]
    public Patient Patient { get; set; }

    [JsonProperty(PropertyName = "guardian_id")]
    public int GuardianID
    {
        get { return Guardian.ID; }
        set { Guardian.ID = value; }
    }

    [JsonProperty(PropertyName = "guardian_name")]
    public string GuardianName
    {
        get { return Guardian.Name; }
        set { Guardian.Name = value; }
    }

    [JsonProperty(PropertyName = "patient_id")]
    public int PatientID
    {
        get { return Patient.ID; }
        set { Patient.ID = value; }
    }

    [JsonProperty(PropertyName = "patient_name")]
    public string PatientName
    {
        get { return Patient.Name; }
        set { Patient.Name = value; }
    }
}

Et comment l'utiliser :

var pairs = JsonConvert.DeserializeObject<Pair[]>(response.Content);

if (pairs.Any())
{
    var pair = pairs[0];
    Console.WriteLine(pair.Guardian.Name);
    Console.WriteLine(pair.Patient.Name);
}

9voto

Patrick Hofman Points 22166

Pas en un seul appel, et il semble que les données soient un tableau, ce qui nécessite un peu plus de travail.

Zip est la méthode clé ici pour joindre les deux listes d'objets séparées :

Guardian[] guardians = JsonConvert.DeserializeObject<Guardian[]>(response.Content);
Patient[] patients = JsonConvert.DeserializeObject<Patient[]>(response.Content);

var combined = guardians.Zip(patients, (g, p) => Tuple.Create(g, p)).ToList();

Il serait beaucoup plus facile de lire le JSON en une seule fois, en un seul objet.

8voto

Peter B Points 69

On ne peut pas le faire en un seul appel avec les types que vous montrez. Vous pouvez essayer d'utiliser le générique <T> pour chaque type, et vous devrez également utiliser des tableaux ou des listes pour le type de retour, car la fonction source JSON est un tableau :

var guardians = JsonConvert.DeserializeObject<Guardian[]>(response.Content);
var patients = JsonConvert.DeserializeObject<Patient[]>(response.Content);

Et puis combinez les deux si vous avez besoin qu'ils soient jumelés. Par exemple, si vous êtes sûr d'avoir toujours un seul de chaque :

var pair = new Pair(guardians[0], patients[0]);

1voto

Michał Turczyn Points 16193

Une autre approche serait de créer une classe qui correspond au format JSON, c'est-à-dire une classe avec quatre propriétés avec les noms correspondants. Ensuite, désérialisez JSON dans cette classe et utilisez-la dans votre code (définissez les propriétés des objets avec les valeurs de JSON, passez l'objet désérialisé au constructeur d'une autre classe).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X