Serial serialization of Bson array (de) using Json.NET

I am just 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:

It is not possible to deserialize the current JSON object (for example, {"name": "value"}) to type 'System.String []', because a JSON array is required for the description type (for example, [1,2,3]).

To fix this error, either change the JSON to a JSON array (for example, [1,2,3]), or change the deserialized type to be a regular .NET type (for example, not a primitive type of integer type, but not a collection type, for example array or list) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to a type to force it to deserialize the JSON object.

How can I make this work?

+6
source share
4 answers

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 parameter is required because the BSON data specification does not store metadata about whether the root value is an object or an array.

+15
source

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

In any case, I was able to work around the problem in several ways:

  • Detach to the 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 external 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.

+5
source

In general, you can first check the data type before setting ReadRootValueAsArray to true, for example:

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

I know this is an old thread, but I found easy deserialization using the power of MongoDB.Driver

You can use BsonDocument.parse (JSONString) to deserialize the JSON object, so use this to deserialize the array of strings:

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

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

0
source

Source: https://habr.com/ru/post/946468/


All Articles