using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json.Linq;
public static class BsonExtensions
public static BsonDocument ToBsonDocument(this JsonElement e, bool writeRootArrayAsDocument = false, bool tryParseDateTimes = false) =>
new(e.EnumerateObject().Select(p => new BsonElement(p.Name, p.Value.ToBsonValue(tryParseDateTimes)))),
JsonValueKind.Array when writeRootArrayAsDocument =>
new(e.EnumerateArray().Select((v, i) => new BsonElement(i.ToString(NumberFormatInfo.InvariantInfo), v.ToBsonValue(tryParseDateTimes)))),
_ => throw new NotSupportedException($"ToBsonDocument: {e}"),
public static BsonValue ToBsonValue(this JsonElement e, bool tryParseDateTimes = false) =>
JsonValueKind.String when tryParseDateTimes && e.TryGetDateTime(out var v) => BsonValue.Create(v),
JsonValueKind.String => BsonValue.Create(e.GetString()),
JsonValueKind.Number when e.TryGetInt32(out var v) => BsonValue.Create(v),
JsonValueKind.Number when e.TryGetInt64(out var v) => BsonValue.Create(v),
JsonValueKind.Number when e.TryGetDouble(out var v) => BsonValue.Create(v),
JsonValueKind.Null => BsonValue.Create(null),
JsonValueKind.True => BsonValue.Create(true),
JsonValueKind.False => BsonValue.Create(false),
JsonValueKind.Array => new BsonArray(e.EnumerateArray().Select(v => v.ToBsonValue(tryParseDateTimes))),
JsonValueKind.Object => e.ToBsonDocument(false, tryParseDateTimes),
_ => throw new NotSupportedException($"ToBsonValue: {e}"),
public static void Test()
foreach (var json in GetJson())
public static void Test(string json)
using var jsonDoc = JsonDocument.Parse(json);
var bsonDoc = jsonDoc.RootElement.ToBsonDocument(true);
var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.RelaxedExtendedJson };
var newJson = bsonDoc.ToJson(jsonWriterSettings);
Console.WriteLine(newJson);
if (jsonDoc.RootElement.ValueKind == JsonValueKind.Array)
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json), new JArray(JObject.Parse(newJson).Properties().Select(p => p.Value))));
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(newJson)));
static IEnumerable<string> GetJson() =>
"title": "example glossary",
"GlossTerm": "Standard Generalized Markup Language",
"Abbrev": "ISO 8879:1986",
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
[1, 2, 3, null, "hello", [[0]], {"foo" : "bar"}, 15226303390001100]
{ "datetime" : { "$date" : 152263033900000 } }
public static void TestArray()
[1, 2, 3, null, "hello", [[0]], {"foo" : "bar"}]
var bsonData = BsonDocument.Parse(json);
var newJson = bsonData.ToJson();
Console.WriteLine(newJson);
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("{0} version: {1}", typeof(BsonDocument).Assembly.GetName().Name, typeof(BsonDocument).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");