1
votes

Désérialiser le json dynamique en objet .NET générique

Quelle est la meilleure façon de désérialiser la réponse JSON suivante en un objet générique? Par exemple, je voudrais accéder au message de réponse et à la liste des erreurs (et accéder au nom du champ et au message d'erreur de celui-ci).

string message = genericObject.message
foreach (error errorElement in genericObject.errors)
{
  string errorField = errorElement.fieldName;
  string errorDescription = errorElement.errorMessage;
}

Modifier:

I souhaite accéder à l'objet JSON d'une manière comme celle-ci

{
  "message": "The given data was invalid.",
  "errors": {
      "name": [
          "Name is required."
      ],
      "gender": [
          "Gender is required."
      ],
      "date_of_birth": [
          "Date of birth is required."
      ]
  }
}

Édition 2:

Je ne connais pas au préalable les champs d'erreur possibles.


5 commentaires

Qu'entendez-vous exactement par "objet générique"? Si vous voulez dire quelque chose avec , ne pouvez-vous pas simplement nous dire quels objets sont impliqués? Si vous voulez dire quelque chose comme dynamique , veuillez le dire.


Je créerais une classe appropriée pour ce json, quelque chose comme public class Response {public string Message {get; ensemble; } Dictionnaire public > Erreurs {get; } = nouveau dictionnaire > (); }


J'ai apporté quelques modifications pour clarifier ma question.


Des mots comme «générique» et «dynamique» peuvent être source de confusion car ils ont une signification très spécifique. Dans ce cas, vous n'avez pas besoin de créer quelque chose de complexe ou de générique ou d'utiliser dynamic . Je pense que ce que vous voulez, c'est ceci: stackoverflow.com/questions/2546138/... . Ignorez la partie de la question qui semble différente de la vôtre et regardez les réponses.


Avez-vous essayé le cours que j'ai fourni dans mon commentaire ci-dessus? Vous pouvez le désérialiser avec quelque chose comme JsonConvert.DeserializeObject (json) .


4 Réponses :


2
votes

Il existe plusieurs façons de procéder.

L'assembly System.Web.Helpers contient la classe Json que vous pouvez faire:

var deserializedObject = JsonConvert.DeserializeObject<dynamic>(json);

Une autre façon serait d'utiliser le Newtonsoft.Json a> paquet nuget:

dynamic decodedObject = Json.Decode(json);


0 commentaires

1
votes

Si vous souhaitez utiliser Newtonsoft.Json , vous pouvez utiliser: < pré> XXX


0 commentaires

1
votes

vous devrez créer les classes suivantes:
RootObject.cs contenant les propriétés suivantes:

var message = inputObj.Message;
var nameErrors = inputObj.Errors;
var firstNameError = inputObj.Errors.Name[0];

Errors.cs , contenant les propriétés suivantes:

var inputObj = JsonConvert.DeserializeObject<RootObject>(json);

Et puis vous lisez le tout comme ceci:

public class Errors
{
    [JsonProperty("name")]
    public string[] Name { get; set; }

    [JsonProperty("gender")]
    public string[] Gender { get; set; }

    [JsonProperty("date_of_birth")]
    public string[] DateOfBirth { get; set; }
}

inputObj sera de type RootObject et json est le JSON que vous recevez.

Si vous l'avez implémenté correctement, utilisez-le comme ceci:

public class RootObject
{
    [JsonProperty("message")]
    public string Message { get; set; }

    [JsonProperty("errors")]
    public Errors Errors { get; set; }
}

Voici un visuel: Affichage de l'objet entier, rempli avec les propriétés: entrez la description de l'image ici

L'erreur "principale": entrez la description de l'image ici

Si vous avez des questions, n'hésitez pas à les poser.


2 commentaires

Je ne sais pas à quels champs d'erreur je peux m'attendre à l'avance.


Si cela signifie simplement que fieldName peut contenir des valeurs différentes, je n'utiliserais pas dynamic . Je m'en éloignerais à moins qu'il n'y ait une raison très précise pour laquelle vous en avez besoin. Si les données que vous recevez sont dans une structure prévisible et que seules les valeurs changent (ce qui est la plupart du temps), vous pouvez simplement définir une classe (ou en générer une en utilisant json2csharp et désérialisez cela.



2
votes

Puisque vous dites que vous ne savez pas quels "champs d'erreur" seront présents, un dictionnaire est la meilleure façon de procéder.

Voici un exemple simple:

string message = genericObject.Message;
foreach (var errorElement in genericObject.Errors) // see note about var below
{
  string errorField = errorElement.Key;
  foreach (string errorDescription in errorElement.Value)
  {
    // process errorField + errorDescription here
  }
}

Lors de l'exécution de ceci dans LINQPad , j'obtiens ce résultat:

 exemple de sortie LINQPad

Vous pouvez même ajouter votre propre code à partir de votre question:

string json = File.ReadAllText(@"d:\temp\test.json");
var genericObject = JsonConvert.DeserializeObject<Response>(json);

string message = genericObject.Message;
foreach (var errorElement in genericObject.Errors) // see note about var below
{
  string errorField = errorElement.Key;
  string errorDescription = errorElement.Value.FirstOrDefault(); // see below
}

Note 1: Le résultat de l'itération d'un dictionnaire est un KeyValuePair , dans ce cas ce serait un KeyValuePair > .

Remarque 2: Vous avez montré que JSON avait un tableau pour chaque champ, donc errorElement.errorMessage ne fonctionnera pas correctement car vous pouvez avoir plusieurs messages d'erreur.

Vous pouvez cependant imbriquer certaines boucles pour les traiter toutes:

void Main()
{
    string json = File.ReadAllText(@"d:\temp\test.json");
    var response = JsonConvert.DeserializeObject<Response>(json);
    response.Dump();
}

public class Response
{
    public string Message { get; set; }

    public Dictionary<string, List<string>> Errors { get; }
        = new Dictionary<string, List<string>>();
}


0 commentaires