10
votes

Tableau BSON (DE) sérialisation avec json.net

J'essaie simplement de sérialiser et de désérialiser un tableau de chaînes au format BSON à l'aide de JSON.NET, mais le code suivant échoue: XXX

Message d'exception:

ne peut pas désérialiser l'objet JSON actuel (par exemple, {"nom": "valeur"}) dans le type 'system.string []' car le type nécessite une matrice JSON (par exemple [1,2,3]) pour désérialiser correctement. .

Pour corriger cette erreur, changez le JSON en une matrice JSON (par exemple, [1,2,3]) ou modifier le type déséréalisé de sorte qu'il s'agisse d'un type de .NET normal (par exemple, pas un type primitif comme entier, pas un type de collecte comme un tableau ou une liste) qui peut être désérialisé à partir d'un objet JSON. JSONOBJECTTRIBUTE peut également être ajouté au type pour la forcer à désérialiser à partir d'un objet JSON.

Comment puis-je obtenir ceci pour travailler?


0 commentaires

5 Réponses :


6
votes

HMMM, de l'endroit où je suis assis, votre code devrait fonctionner, mais Json.net semble penser que votre gamme Serialized Strings est un dictionnaire. Cela pourrait être car, selon le Spécification BSON , les tableaux sont réellement sérialisés comme une liste de la valeur de la clé paires comme les objets font. Les clés dans ce cas sont simplement les représentations de chaîne des valeurs d'indice de tableau.

Dans tous les cas, j'ai pu contourner le problème de différentes manières: p>

  1. désériorialiser à un dictionnaire puis le reconverser manuellement à un tableau. P> XXX PRE> LI>

  2. enveloppez le tableau dans un objet extérieur. p>

    var jsonSerializer = new JsonSerializer();
    var obj = new Wrapper { Array = new string[] { "A", "B" } };
    
    // Serialization
    byte[] bytes;
    using (var ms = new MemoryStream())
    using (var bson = new BsonWriter(ms))
    {
        jsonSerializer.Serialize(bson, obj);
        bytes = ms.ToArray();
    }
    
    // Deserialization
    using (var ms = new MemoryStream(bytes))
    using (var bson = new BsonReader(ms))
    {
        obj = jsonSerializer.Deserialize<Wrapper>(bson);
    }
    


2 commentaires

Merci ou l'analyse et des travaux possibles. Dans mon cas, bien qu'ils soient un peu difficiles à mettre en œuvre car j'ai besoin de ce code pour travailler avec des types inconnus. J'ai ouvert un problème sur le site Web de Codéplex: JSON.CODEPLEX.COM/workItem/24365


@Xavierpoinas La deuxième solution, enveloppant la matrice dans un objet extérieur, fonctionne bien pour les types inconnus. Changez simplement le type de propriété de la classe wrapper, c'est-à-dire valeur d'objet public {obtenir; ensemble; } au lieu de chaîne publique [] array {obtenir; ensemble; } et vous pouvez également l'utiliser avec des types non-réseau également. Il est facile de créer une classe d'assistance qui fait automatiquement l'emballage / décalage automatique.



18
votes

Ensemble Readrootvalueasarray sur True sur Bossheader

http: //james.newtonking. com / projects / json / help / index.html? topic = html / p_newtonsoft_json_bson_bsonreader_readrootvalueasarray.htm

Ce paramètre est requis car la spécification de données BSON ne permet pas de sauvegarder des métadonnées sur le point de savoir si la valeur racine est un objet ou un tableau.


0 commentaires

1
votes

En général, vous pouvez vérifier le type de données avant de définir Readrootvalueasarray à true, comme celui-ci:

if (typeof(IEnumerable).IsAssignableFrom(type)) 
    bSonReader.ReadRootValueAsArray = true;


0 commentaires

1
votes

Je sais que c'est un vieux fil, mais j'ai découvert une désérialisation facile tout en utilisant la puissance de Mongodb.Driver

Vous pouvez utiliser BSONDOCument.PARSE (JSONSRING) pour désérialiser un objet JSON afin de désérialiser une matrice de chaîne Utilisez ceci: xxx

désériializedarray peut ensuite être utilisé comme une matrice telle qu'une boucle foreach.


0 commentaires

1
votes

Comme expliqué dans Cette réponse par James Newton-King , le format BSON ne permet pas de sauvegarder des métadonnées si la valeur racine est une collection, ce qui permet de définir BSONDAREADER.ReadrootvalueasArray Code> Deco Commençant à désérialiser.

Un moyen facile de le faire, lors de la désériorialisation de certains POCO Type (plutôt que dynamique code> ou jToken code>), est d'initialiser le lecteur en fonction de la question de savoir si le type racine sera sérialisé à l'aide d'un contrat de tableau . Les méthodes d'extension suivantes font ceci: p> xxx pré>

Vous pouvez simplement faire simplement: p> xxx pré>

notes: p>

  • Support BSON a été déplacé vers son propre package, Newtonsoft. Json.bson code> , dans json.net 10.0.1 . Dans cette version et des versions ultérieures BSONDAREADER remplace le maintenant-obsolète Bossreader Code> . P> LI>

  • Les mêmes méthodes d'extension peuvent être utilisées pour désérialiser un dictionnaire, par exemple: p>

    var newDictionary = BsonExtensions.Deserialize<SortedDictionary<int, string>>(bytes);
    

  • 0 commentaires