Comment faire pour convertir en JSON à la liste de chaîne, lorsque certains des objets JSON sont de chaîne et certains sont ensemble?
Mon JSON ressemble
{
"d": {
"__type": "CubeJsonData",
"SessionID": null,
"Code": 0,
"Message": "",
"Rows": {},
"Columns": {
"Place 1": [
0,
1
],
"Place 2": [
0,
2,
4,
6
],
},
"Set": [
[
"Number 1"
],
[
"Number 2"
],
[
"Number 3"
]
]
}
}
J'ai besoin d'obtenir les valeurs suivantes
List<string> Columns must contain: "Place 1", "Place 2"
List<string> Set must contain: "Number 1", "Number 2", "Number 3"
Mon interlocuteur est
var settings = new JsonSerializerSettings();
settings.Converters.Add(new AssosiativeArrayConverter());
var staffAlerts = JsonConvert.DeserializeObject<List<AlertDetails>>(jo.ToString(), settings);
Mon JsonConverter est
class AssosiativeArrayConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string)) || (objectType == typeof(List<string>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var l = new List<string>();
reader.Read();
while (reader.TokenType != JsonToken.EndArray)
{
l.Add(reader.Value as string);
reader.Read();
}
return l;
}
else
{
return new List<string> { reader.Value as string };
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{//to do
}
}
Ma classe est
class StaffDetail
{
public string __type { get; set; }
public string SessionID { get; set; }
public string Code { get; set; }
public string Message { get; set; }
[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Rows { get; set; }
[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Columns { get; set; }
[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Set { get; set; }
}
J'obtiens une erreur
Ne peut pas désérialiser l'actuel objet JSON (par exemple, {"name":"valeur"}) dans le " type de Système.Les Collections.Génériques.Liste`1[ReportingServicesAlerts.AlertDetails] " parce que le type requiert un tableau JSON (par exemple, [1,2,3]) pour désérialiser correctement.
Pour corriger cette erreur soit modifier le JSON d'un tableau JSON (par exemple, [1,2,3]) ou de modifier le désérialisé type de sorte qu'il est normal .NET type (par exemple, pas un type primitif comme entier, pas un type de collection comme un tableau ou une Liste) qui peut être désérialisé à partir d'un objet JSON. JsonObjectAttribute peuvent également être ajoutés à la type pour le forcer à désérialiser à partir d'un objet JSON.
Pouvez-vous m'aider à comprendre ce que je fais mal?
- tout d'abord, vous avez eu une erreur dans votre json, juste avant "et" il ne devrait pas être délimité par des virgules là, je vais essayer moi-même dans un tout en travaillant sur elle 🙂 ... mais je crois que vous devriez être en mesure de le faire sans tout ce code ...
- CORRECTION 🙂 ... 2 vit au-dessus de "Définir"
Vous devez vous connecter pour publier un commentaire.
Vous avez beaucoup de problèmes ici. Permettez-moi de commencer avec la raison pour laquelle vous obtenez cette erreur: votre JSON contient un seul objet extérieur, mais vous essayez de désérialiser dans une liste. Cela ne fonctionnera pas. Si il ya juste un seul objet dans le JSON, vous avez besoin pour désérialiser un objet unique.
Deuxième question, les données de votre
StaffDetail
classe n'est pas au top niveau de votre JSON; il est d'un niveau vers le bas-dans la valeur de lad
propriété de l'extérieur d'objet JSON. Pour résoudre ce problème, vous devez introduire une classe wrapper et désérialiser les en que. Ensuite, vous pouvez récupérer leStaffDetail
de l'emballage.Troisième question, il semble que vous essayez d'aplatir la
Columns
etSet
de données à partir du JSON enList<string>
propriétés dans votre classe. Il semble que vous avez correctement réalisé que vous avez besoin d'un convertisseur pour ce faire, cependant, votre convertisseur ne gère pas les données JSON correctement-- c'est en supposant qu'il se passe pour obtenir un simple tableau de chaînes de caractères ou une chaîne simple. NiColumns
niSet
est structuré de cette façon dans le JSON, et en outre, les données sont structurées différemment pour chacun d'eux. Le premier est un objet contenant des propriétés dont les valeurs sont des tableaux de nombres entiers. Ce dernier est un tableau de tableaux de chaînes de caractères. Puisqu'ils sont de différentes structures, elles doivent être traitées différemment. Je voudrais suggérer à l'aide de deux convertisseurs dans ce cas.Quatrièmement, alors que vous avez correctement décorer votre
StaffDetail
classe avec[JsonConverter]
attributs pour indiquer quelles propriétés doivent utiliser votre convertisseur, vous incorrectement également ajouter le convertisseur pour le sérialiseur paramètres. Le problème avec ceci est que votre convertisseur est dit dansCanConvert
qu'il peut gérer n'importe quelle chaîne ou une liste de chaînes de caractères. Si vous appliquez le convertisseur dans les paramètres qui signifie que Json.Net essaie d'utiliser votre convertisseur pour tout bien n'importe où, qui est soit une chaîne ou une liste de chaînes de caractères. Clairement, vous ne voulez pas cela, vos converter est vraiment destinée à traiter un cas particulier.Cinquième, il semble que vous avez aussi décorée à votre
Rows
propriété avec un[JsonConverter]
attribut, mais le JSON montre un objet vide. Sera ce domaine ont toutes les données qui vous intéresse? Si non, il suffit de le déclarer commeobject
; si vous ne les soins, s'il vous plaît montrer un exemple de ce qui pourrait être là. Ou si vous savez qu'il sera structuré de la même commeColumns
ouSet
, alors vous pouvez la garder commeList<string>
et de réutiliser l'un de ces convertisseurs.Il y a aussi quelques autres questions mineures dans votre question, telle que votre JSON être invalide en raison d'une virgule supplémentaire (déjà signalé par @frno), et le fait que votre appel à
JsonConvert.DeserializeObject()
mentionne une classe appeléeAlertDetails
mais la classe vous montrer, c'est en fait le nomStaffDetail
. Mais nous allons craie ceux à simple copier-coller des erreurs.Ouf!
OK, alors comment pouvons-nous corriger tout cela?
Commençons avec vos classes. J'ai mentionné que vous avez besoin d'une classe wrapper vos données sont en fait un niveau plus bas dans le JSON; voici ce qui pourrait ressembler à:
Pour votre
StaffDetail
classe, j'ai changé leColumns
etSet
propriétés à utiliser différents convertisseurs, depuis le JSON est différente pour chacun. Je vais définir les convertisseurs suivant. J'ai aussi changé le type deRows
àobject
et enlevé le[JsonConverter]
attribut pour l'instant, puisqu'il n'est pas clair à partir de la question de savoir comment ce champ doit être traitée. Si les données seront structurés commeColumns
ouSet
ensuite, vous pouvez modifier et utiliser le convertisseur approprié, comme je l'ai mentionné.Ici, c'est le convertisseur qui va gérer le
Columns
de données. Ce convertisseur permet de prendre un objet JSON et d'en extraire les noms de propriété en une liste de chaînes de caractères.Ici, c'est le convertisseur qui va gérer le
Set
de données. Ce convertisseur va prendre un tableau de tableaux de chaînes de caractères et de le convertir dans un plat de liste de chaînes de caractères.Pour désérialiser, vous pouvez appeler
JsonConvert.DeserializeObject()
comme ça. Remarquez comment je désérialiser dans leWrapper
classe, puis récupérer leStaffDetail
d'elle. Notez également que je n'ai pas besoin (et ne devrait pas dans ce cas) passer les convertisseurs de la deserializer. Ils seront ramassés automatiquement et en temps opportun en vertu de la[JsonConverter]
attributs sur laStaffDetail
des propriétés de la classe.Ici est simple programme de démonstration pour montrer comment tout cela fonctionne:
De sortie:
votre Json est un peu bizarre, si vous pouvez le changer. Néanmoins, corriger les classes :
(+ N'OUBLIEZ PAS DE RETIRER UNE VIRGULE, J'AI ÉCRIT SUR )
et un seul moyen simple d'obtenir tous les
puis juste obtenir les propriétés de tout ce que vous voulez, comme
Columns
objet, et non les valeurs.