Bson array (de)serialization with Json.NET

萝らか妹 提交于 2019-12-30 17:39:11

问题


I am simply trying to serialize and deserialize a string array in Bson format using Json.NET, but the following code fails:

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

Exception message:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.String[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

How can I get this to work?


回答1:


Set ReadRootValueAsArray to true on BsonReader

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

This setting is required because the BSON data spec doesn't save metadata about whether the root value is an object or an array.




回答2:


Hmmm, from where I sit, your code should work, but Json.Net seems to think that your serialized array of strings is a dictionary. This could be because, according to the BSON specification, arrays actually do get serialized as a list of key-value pairs just like objects do. The keys in this case are simply the string representations of the array index values.

In any case, I was able to work around the issue in a couple of different ways:

  1. Deserialize to a Dictionary and then manually convert it back to an array.

    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. Wrap the array in an outer object.

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

    Then serialize and deserialize using the wrapper object.

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

Hope this helps.




回答3:


In general, you could check data type first before set ReadRootValueAsArray to true, like this:

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



回答4:


I know this is an old thread but I discovered a easy deserialization while using the power of MongoDB.Driver

You can use BsonDocument.parse(JSONString) to deserialize a JSON object so to deserialize a string array use this:

string Jsonarray = "[\"value1\", \"value2\", \"value3\"]";
BsonArray deserializedArray = BsonDocument.parse("{\"arr\":" + Jsonarray + "}")["arr"].asBsonArray;

deserializedArray can then be used as any array such as a foreach loop.



来源:https://stackoverflow.com/questions/16910369/bson-array-deserialization-with-json-net

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!