Comment gérer à la fois un élément unique et un tableau pour la même propriété à l'aide de JSON.net
J'essaie de résoudre mon SendGridPlus bibliothèque de traiter avec SendGrid événements, mais je vais avoir quelques problèmes avec le manque d'uniformité dans le traitement de catégories dans l'API.
Dans l'exemple suivant charge utile prises à partir de la SendGrid de référence de l'API, vous remarquerez que la category
propriété pour chaque élément peut être une chaîne ou un tableau de chaînes de caractères.
[
{
"email": "[email protected]",
"timestamp": 1337966815,
"category": [
"newuser",
"transactional"
],
"event": "open"
},
{
"email": "[email protected]",
"timestamp": 1337966815,
"category": "olduser",
"event": "open"
}
]
Il semble que mon options pour faire JSON.NET comme ce sont de fixation de la chaîne avant qu'elle arrive, ou de la configuration de JSON.NET pour accepter les données incorrectes. Je préfère ne pas faire de traitement de chaîne si je peux sortir avec elle.
Est-il un autre moyen que je peux gérer cela à l'aide de Json.Net?
OriginalL'auteur Robert McLaws | 2013-09-25
Vous devez vous connecter pour publier un commentaire.
La meilleure façon de gérer cette situation est d'utiliser un
JsonConverter
.Avant de nous rendre à la convertisseur, nous avons besoin de définir une classe pour désérialiser les données. Pour le
Categories
propriété qui peut varier entre un élément unique et un tableau, le définir comme unList<string>
et de marquer avec un[JsonConverter]
attribut de sorte que JSON.Net saurez utiliser le convertisseur personnalisé pour cette propriété. Je vous recommande également à l'aide de[JsonProperty]
attributs de sorte que les propriétés de membre ne peut être donnée des noms significatifs indépendant de ce qui est défini dans le JSON.Ici est de savoir comment je voudrais mettre en œuvre le convertisseur. Notez que j'ai fait le convertisseur générique, de sorte qu'il peut être utilisé avec des chaînes ou d'autres types d'objets que nécessaire.
Voici un court programme de démonstration le convertisseur dans l'action avec vos données d'échantillonnage:
Et enfin, voici la sortie de la ci-dessus:
Violon: https://dotnetfiddle.net/lERrmu
MODIFIER
Si vous avez besoin d'aller dans l'autre sens, c'est à dire sérialiser, tout en gardant le même format, vous pouvez mettre en œuvre la
WriteJson()
méthode du convertisseur, comme illustré ci-dessous. (Assurez-vous de retirer leCanWrite
de remplacer ou de le changer pour revenirtrue
, ou d'autreWriteJson()
ne sera jamais appelé.)Violon: https://dotnetfiddle.net/XG3eRy
Pas de problème; heureux que vous avez trouvé utile.
Vous avez certainement sont l'homme.
Excellent! C'est ce que ive été la recherche de. @BrianRogers, si jamais vous êtes à Amsterdam, les boissons sont sur moi!
Vous n'avez pas besoin d'ajouter le convertisseur de la
DeserializeObject
appel si vous utilisez le[JsonConverter]
attribut sur la liste des biens dans votre classe, comme indiqué dans la réponse ci-dessus. Si vous ne pas utiliser l'attribut, alors, oui, vous avez besoin de passer du convertisseurDeserializeObject
.OriginalL'auteur Brian Rogers
Je travaillais sur ce pendant des siècles, et grâce à Brian pour sa réponse.
Tout ce que je suis en ajoutant le vb.net réponse!:
puis dans votre classe:
Espère que cela vous fait gagner un certain temps
OriginalL'auteur grantay
J'ai eu un Problème similaire.
Mon Json Demande a été complètement inconnu pour moi.
Je ne savais que le.
Il y aura un objectId en elle et quelques anonym paires clé-valeur ET les tableaux.
Je l'ai utilisé pour un Modèle EAV j'ai fait:
Mon JSON Demande:
Ma Classe j'ai défini:
et maintenant que je veux désérialiser les attributs inconnus avec sa valeur et des tableaux dans mon Convertisseur ressemble à ça:
Alors maintenant, chaque fois que je reçois un AnonymObject je peux parcourir le Dictionnaire et à chaque fois il y a mon Drapeau "ValueDummyForEAV" - je passer à la liste, à lire la première ligne et de diviser les valeurs. Après cela, j'ai supprimer le premier élément de la liste et aller à l'itération à partir du Dictionnaire.
Peut-être quelqu'un a le même problème et peut l'utiliser 🙂
Ce qui concerne
André
OriginalL'auteur Andre Fritzsche
Vous pouvez utiliser un
JSONConverterAttribute
comme on la trouve ici: http://james.newtonking.com/projects/json/help/En supposant que vous avez une classe qui ressemble à
Vous avais décorer la catégorie de la propriété comme vu ici:
privé de la chaîne de charge utile = "[\n" + "{\n" + "\"email\": \"[email protected]\",\n" + "\"timestamp\": 1337966815,\n" + "\"smtp-id\": \"<[email protected]>\",\n" + "\"catégorie\": \"newuser\",\n" + "\"event\": \"cliqué\"\n" + "}, " + "{"+ "\"e-mail\": \"[email protected]\",\n" + "\"timestamp\": 1337969592,\n" + "\"smtp-id\": \"<[email protected]>\",\n" + "\"catégorie\": [\"somestring1\",\"somestring2\"],\n" + "\"event\": \"traitées\",\n" + "}\n" + "]";
Il traite le premier objet fine et traitées avec aucun tableau magnifiquement. Mais quand j'ai créé un tableau pour le 2ème objet, il a échoué.
Sans voir ton code, je suppose que vous êtes en laissant le lecteur est mal positionné après avoir lu le JSON. Au lieu de tenter de l'utiliser directement au lecteur, il est préférable de charger un JToken objet du lecteur, et à partir de là. Voir ma réponse pour un travail de mise en œuvre du convertisseur.
Beaucoup plus de détails dans les de Brian réponse. L'utiliser 🙂
OriginalL'auteur Tim Gabrhel
Comme une variation mineure de la grande réponse par Brian Rogers, voici deux versions remaniées de
SingleOrArrayConverter<T>
.Tout d'abord, voici une version qui fonctionne pour tous les
List<T>
pour chaque type deT
qui n'est pas lui-même une collection:Il peut être utilisé comme suit:
Notes:
Le convertisseur évite la nécessité de pré-charger l'intégralité de la valeur JSON dans la mémoire comme un
JToken
hiérarchie.Le convertisseur ne s'applique pas aux listes dont les éléments sont également sérialisé que les collections, par exemple
List<string []>
Le Booléen
canWrite
argument passé au constructeur décide de re-sérialiser un seul élément des listes de JSON valeurs ou JSON tableaux.Du convertisseur
ReadJson()
utilise leexistingValue
si la pré-alloué de manière à soutenir la population d'obtenir uniquement les membres de la liste.Deuxièmement, voici une version qui fonctionne avec d'autres génériques de collections telles que
ObservableCollection<T>
:Ensuite, si votre modèle à l'aide, par exemple, un
ObservableCollection<T>
pour certainsT
, vous pouvez l'appliquer comme suit:Notes:
SingleOrArrayListConverter
, leTCollection
type doit être en lecture/écriture et d'avoir un constructeur sans paramètre.De démonstration de jouer avec l'unité de base des tests de ici.
OriginalL'auteur dbc
J'ai trouvé une autre solution qui permet de gérer la catégorie comme une chaîne de caractères ou un tableau en utilisant l'objet. De cette façon, je n'ai pas besoin de gâcher avec le sérialiseur json.
S'il vous plaît donner un coup d'oeil si vous avez le temps et dites-moi ce que vous en pensez. https://github.com/MarcelloCarreira/sendgrid-csharp-eventwebhook
Il est basé sur la solution à https://sendgrid.com/blog/tracking-email-using-azure-sendgrid-event-webhook-part-1/ mais j'ai aussi ajouté la date de conversion à partir d'un timestamp, mis à jour les variables de manière à refléter les SendGrid modèle (et de fait des catégories).
J'ai également créé un gestionnaire de base d'authentification en option. Voir la ashx et les fichiers d'exemples.
Merci!
OriginalL'auteur MarcelloCarreira