J'aime vraiment la ExpandoObject
compilation d'un objet dynamique côté serveur au moment de l'exécution, mais j'ai du mal à aplatir cette chose lors de la sérialisation JSON. Tout d'abord, j'instancie l'objet:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
Jusqu'ici tout va bien. Dans mon contrôleur MVC, je veux ensuite envoyer ceci en tant que JsonResult, donc je fais ceci:
return new JsonResult(expando);
Cela sérialise le JSON dans le ci-dessous, pour être consommé par le navigateur:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
MAIS, ce que j'aimerais vraiment, c'est voir ceci:
{SomeProp: SomeValueOrClass}
Je sais que je peux y parvenir si j'utilise à la dynamic
place de ExpandoObject
- JsonResult
est capable de sérialiser les dynamic
propriétés et les valeurs en un seul objet (sans clé ni valeur), mais la raison pour laquelle je dois utiliser ExpandoObject
est que je ne sais pas tout les propriétés que je veux sur l'objet jusqu'à l'exécution , et pour autant que je sache, je ne peux pas ajouter dynamiquement une propriété à un dynamic
sans utiliser un ExpandoObject
.
Je devrais peut-être passer au crible les affaires "Clé", "Valeur" dans mon javascript, mais j'espérais comprendre cela avant de l'envoyer au client. Merci de votre aide!
Réponses:
Vous pouvez également créer un JSONConverter spécial qui ne fonctionne que pour ExpandoObject, puis l'enregistrer dans une instance de JavaScriptSerializer. De cette façon, vous pouvez sérialiser des tableaux d'expansion, des combinaisons d'objets expando et ... jusqu'à ce que vous trouviez un autre type d'objet qui ne soit pas sérialisé correctement ("comme vous le souhaitez"), puis vous créez un autre convertisseur, ou ajoutez un autre type à celui-là. J'espère que cela t'aides.
Utilisation du convertisseur
la source
NotImplementedException
ajouter quelque chose commeserializer.Deserialize<ExpandoObject>(json);
, @theburningmonk propose une solution qui a fonctionné pour moi.En utilisant JSON.NET, vous pouvez appeler SerializeObject pour "aplatir" l'objet expando:
Sortira:
Dans le contexte d'un contrôleur ASP.NET MVC, le résultat peut être renvoyé à l'aide de la méthode Content:
la source
Voici ce que j'ai fait pour obtenir le comportement que vous décrivez:
Le coût est que vous faites une copie des données avant de les sérialiser.
la source
ExpandoObject
vous offre beaucoup plus de flexibilité qu'un simple dictionnaire. Bien que l'exemple ci-dessus ne le démontre pas, vous pouvez utiliser les fonctionnalités dynamiques deExpandoObject
pour ajouter les propriétés que vous souhaitez avoir dans votre JSON. UnDictioanry
objet normal sera converti en JSON sans aucun problème, donc en effectuant la conversion, c'est un moyen simple O (n) de mettre la dynamique facile à utiliserExpandoObject
dans un format qui peut être JSONifié. Vous avez raison cependant, l'exemple ci-dessus serait une utilisation simplifiée duExpandoObject
; un simpleDictionary
serait beaucoup mieux.J'ai résolu ce problème en écrivant une méthode d'extension qui convertit ExpandoObject en une chaîne JSON:
Cela utilise l'excellente bibliothèque Newtonsoft .
JsonResult ressemble alors à ceci:
Et ceci est renvoyé au navigateur:
Et je peux l'utiliser en javascript en faisant ceci (référencé ici ):
J'espère que ça aide!
la source
J'ai pu résoudre ce même problème en utilisant JsonFx .
production:
la source
J'ai poussé le processus d'aplatissement un peu plus loin et j'ai vérifié les objets de liste, ce qui supprime le non-sens de la valeur clé. :)
la source
Cela peut ne pas vous être utile, mais j'avais une exigence similaire, mais j'ai utilisé un SerializableDynamicObject
J'ai changé le nom du dictionnaire en "Fields", puis cela se sérialise avec Json.Net pour produire json qui ressemble à:
{"Fields": {"Property1": "Value1", "Property2": "Value2" etc. où Property1 et Property2 sont des propriétés ajoutées dynamiquement - c'est-à-dire des clés de dictionnaire
Ce serait parfait si je pouvais me débarrasser de la propriété supplémentaire "Fields" qui encapsule le reste, mais j'ai contourné cette limitation.
Réponse déplacée de cette question sur demande
la source
C'est une réponse tardive, mais j'ai eu le même problème, et cette question m'a aidé à les résoudre. En résumé, j'ai pensé que je devrais poster mes résultats, dans l'espoir que cela accélère la mise en œuvre pour les autres.
Tout d'abord, ExpandoJsonResult, dont vous pouvez renvoyer une instance dans votre action. Ou vous pouvez remplacer la méthode Json dans votre contrôleur et la renvoyer là-bas.
Ensuite, le convertisseur (qui prend en charge à la fois la sérialisation et la désérialisation. Voir ci-dessous pour un exemple de dé-sérialisation).
Vous pouvez voir dans la classe ExpandoJsonResult comment l'utiliser pour la sérialisation. Pour désérialiser, créez le sérialiseur et enregistrez le convertisseur de la même manière, mais utilisez
Un grand merci à tous les participants ici qui m'ont aidé.
la source
En utilisant le retour de ExpandoObject dynamique de WebApi dans ASP.Net 4, le formateur JSON par défaut semble aplatir ExpandoObjects en un simple objet JSON.
la source
JsonResult
utiliseJavaScriptSerializer
qui désérialise réellement (le béton)Dictionary<string, object>
comme vous le souhaitez.Il y a une surcharge du
Dictionary<string, object>
constructeur qui prendIDictionary<string, object>
.ExpandoObject
outilsIDictionary<string, object>
(je pense que vous pouvez voir où je vais ici ...)ExpandoObject à un niveau
Une ligne de code, utilisant tous les types intégrés :)
ExpandoObjects imbriqués
Bien sûr, si vous imbriquez des
ExpandoObject
s, vous devrez tous les convertir récursivement enDictionary<string, object>
s:votre code final devenant
la source
Il semble que le sérialiseur transforme l'Expando dans un dictionnaire, puis le sérialise (donc l'activité Clé / Valeur). Avez-vous essayé de désérialiser en tant que dictionnaire, puis de le renvoyer dans un Expando?
la source
J'ai juste eu le même problème et j'ai découvert quelque chose d'assez bizarre. Si je fais:
Cela fonctionne, mais seulement si ma méthode utilise l'attribut HttpPost. Si j'utilise HttpGet, j'obtiens une erreur. Donc ma réponse ne fonctionne que sur HttpPost. Dans mon cas, c'était un appel Ajax afin que je puisse changer HttpGet par HttpPost.
la source