11

Json.NET を使用して文字列配列を Bson 形式でシリアル化および逆シリアル化しようとしていますが、次のコードは失敗します。

var jsonSerializer = new JsonSerializer();
var array = new string [] { "A", "B" };

// Serialization
byte[] bytes;
using (var ms = new MemoryStream())
using (var bson = new BsonWriter(ms))
{
    jsonSerializer.Serialize(bson, array, typeof(string[]));
    bytes = ms.ToArray();
}

// Deserialization
using (var ms = new MemoryStream(bytes))
using (var bson = new BsonReader(ms))
{
    // Exception here
    array = jsonSerializer.Deserialize<string[]>(bson);
}

例外メッセージ:

現在の JSON オブジェクト ({"name":"value"} など) を型 'System.String[]' に逆シリアル化できません。型が正しく逆シリアル化するには JSON 配列 ([1,2,3] など) が必要なためです。

このエラーを修正するには、JSON を JSON 配列 ([1,2,3] など) に変更するか、逆シリアル化された型を通常の .NET 型 (整数のようなプリミティブ型ではなく、コレクション型ではない) に変更します。 JSON オブジェクトから逆シリアル化できる配列またはリスト)。JsonObjectAttribute を型に追加して、強制的に JSON オブジェクトから逆シリアル化することもできます。

どうすればこれを機能させることができますか?

4

5 に答える 5

19

BsonReader で ReadRootValueAsArray を true に設定します

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

BSON データ仕様では、ルート値がオブジェクトか配列かに関するメタデータが保存されないため、この設定が必要です。

于 2013-06-05T21:00:28.633 に答える
6

うーん、私が座っているところから、あなたのコードは機能するはずですが、Json.Net は、シリアル化された文字列の配列が辞書であると考えているようです。これは、BSON 仕様によると、オブジェクトと同じように、配列が実際にはキーと値のペアのリストとしてシリアル化されることが原因である可能性があります。この場合のキーは、単に配列インデックス値の文字列表現です。

いずれにせよ、いくつかの異なる方法で問題を回避することができました。

  1. ディクショナリに逆シリアル化してから、手動で配列に変換します。

    var jsonSerializer = new JsonSerializer();
    var array = new string[] { "A", "B" };
    
    // Serialization
    byte[] bytes;
    using (var ms = new MemoryStream())
    using (var bson = new BsonWriter(ms))
    {
        jsonSerializer.Serialize(bson, array);
        bytes = ms.ToArray();
    }
    
    // Deserialization
    using (var ms = new MemoryStream(bytes))
    using (var bson = new BsonReader(ms))
    {
        var dict = jsonSerializer.Deserialize<Dictionary<string, string>>(bson);
        array = dict.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).ToArray();
    }
    
  2. 配列を外側のオブジェクトでラップします。

    class Wrapper
    {
        public string[] Array { get; set; }
    }
    

    次に、ラッパー オブジェクトを使用してシリアライズおよびデシリアライズします。

    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);
    }
    

お役に立てれば。

于 2013-06-04T07:57:39.123 に答える