Convert MongoDB BsonDocument to valid JSON in C#

落花浮王杯 提交于 2019-11-26 21:33:54

问题


I am working with the MongoDB C# driver. I have a BsonDocument with some data which includes some MongoDB-specific types (like ObjectIDs and ISODates). I want to convert this to a valid general-purpose JSON string. In other words, I can't have something like _id: ObjectId(...) or date: ISODate(...) but would prefer _id: "..." and date: "...". Basically, I want to convert these special types that only MongoDB recognizes to regular strings so they can be parsed more easily. The problem is that a built-in function like .ToJson() (which another StackOverflow answer suggests) doesn't really convert the document to valid JSON at all because it maintains these special types. My document also contains many levels of arrays and sub-documents, so a simple for loop will not suffice. What's the best way to convert a BsonDocument that avoids this problem? I would prefer something built-in rather than manually recursing through the document to fix all the issues.


回答1:


I've ran into the same thing, you can get valid JSON via:

var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
JObject json = JObject.Parse(postBsonDoc.ToJson<MongoDB.Bson.BsonDocument>(jsonWriterSettings));

However it will return something like:

{"_id":{"$oid":"559843798f9e1d0fe895c831"}, "DatePosted":{"$date":1436107641138}}

I'm still trying to find a way to flatten that.




回答2:


How about something like:

JsonConvert.SerializeObject(BsonTypeMapper.MapToDotNetValue(bsonDoc));

For a List of BsonDocument

bsonDocList.ConvertAll(BsonTypeMapper.MapToDotNetValue)



回答3:


Most of the Time for this I use, Json.NET

JsonConvert.SerializeObject(obj); 

Most of the time that does the trick. If need be you can set some JsonSerializerSettings




回答4:


In my opinion the best option is to use Newtonsoft.Json.Bson.BsonReader. Here a complete example:

public string ToJson(BsonDocument bson)
{
    using (var stream = new MemoryStream())
    {
        using (var writer = new BsonBinaryWriter(stream))
        {
            BsonSerializer.Serialize(writer, typeof(BsonDocument), bson);
        }
        stream.Seek(0, SeekOrigin.Begin);
        using (var reader = new Newtonsoft.Json.Bson.BsonReader(stream))
        {
            var sb = new StringBuilder();
            var sw = new StringWriter(sb);
            using (var jWriter = new JsonTextWriter(sw))
            {
                jWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
                jWriter.WriteToken(reader);
            }
            return sb.ToString();
        }
    }
}

I think that this should handle all cases correctly (dates, ids, ...).




回答5:


Here is the way i did it, to skip mongodb _id entry.

var collection = _database.GetCollection<BsonDocument>("test");

var result = await collection.Find(new BsonDocument())
     .Project(Builders<BsonDocument>.Projection.Exclude("_id"))
     .ToListAsync();
var obj = result.ToJson();



回答6:


If you need to use this ASP.NET Core for when you may be returning a model that has BsonDocument to be able to add dynamic data. You can use this JsonConverter implementation based on MarkKGreenway's answer!

 public class BsonDocumentJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(BsonDocument);
        }

        public override bool CanRead
        {
            get
            {
                return false;
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            //string json = (value as BsonDocument).ToJson(); //!NB: this returns BSON not JSON. Why on earth is it called ToJson!?
            string json = JsonConvert.SerializeObject(value);
            writer.WriteRawValue(json);
        }
    }

Then in your Startup.cs just add the following.

  services.AddMvc()
                .AddJsonOptions(options => options.SerializerSettings.Converters.Add(new BsonDocumentJsonConverter()));



回答7:


what about

String json = result.toJson(JsonWriterSettings.builder().objectIdConverter(new Converter<ObjectId>() {
            @Override
            public void convert(ObjectId value, StrictJsonWriter writer) {
                writer.writeString(value.toHexString());
            }
        }).build());



回答8:


If the contents of the BSON document is saved as, below

{
"Date" : "2019-04-05T07:07:31.979Z",
"BSONCONTENT" : {
    "_t" : "MongoDB.Bson.BsonDocument, MongoDB.Bson",
    "_v" : {
        "A" : "XXXX",
        "B" : 234   
           }  
 }     

}

then it works with generic class.

private static T ProcessBsonConversion<T>(BsonDocument data)
    {
        var content = data.GetElement("_v");
        var jsonDataContent= content.Value.AsBsonValue.ToJson();
        return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonDataContent);

    }


来源:https://stackoverflow.com/questions/27132968/convert-mongodb-bsondocument-to-valid-json-in-c-sharp

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