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?
Set ReadRootValueAsArray to true on BsonReader
This setting is required because the BSON data spec doesn't save metadata about whether the root value is an object or an array.
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:
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(); }
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.
In general, you could check data type first before set ReadRootValueAsArray to true, like this:
if (typeof(IEnumerable).IsAssignableFrom(type))
bSonReader.ReadRootValueAsArray = true;
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