将MongoDB BsonDocument转换为C#中的有效JSON

时间:2014-11-25 17:25:47

标签: json mongodb mongodb-.net-driver

我正在使用MongoDB C#驱动程序。我有一个BsonDocument,其中包含一些MongoDB特定类型的数据(如ObjectID和ISODates)。我想将其转换为有效的通用JSON字符串。换句话说,我不能使用_id: ObjectId(...)date: ISODate(...),但更喜欢_id: "..."date: "..."。基本上,我想将只有MongoDB识别的特殊类型转换为常规字符串,以便更容易地解析它们。问题是像.ToJson()这样的内置函数(另一个StackOverflow答案建议)并没有真正将文档转换为有效的JSON,因为它维护了这些特殊类型。我的文档还包含许多级别的数组和子文档,因此简单的for循环是不够的。转换BsonDocument以避免此问题的最佳方法是什么?我更喜欢内置的东西而不是手动递归文档来修复所有问题。

11 个答案:

答案 0 :(得分:15)

我遇到了同样的事情,你可以通过以下方式获得有效的JSON:

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

但它会返回类似的内容:

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

我仍在努力找到一种方法来压扁它。

答案 1 :(得分:4)

我使用的大部分时间都是Json.NET

JsonConvert.SerializeObject(obj); 

大部分时间都可以解决问题。如果需要,您可以设置一些 JsonSerializerSettings

答案 2 :(得分:3)

在我看来,最好的选择是使用Newtonsoft.Json.Bson.BsonReader。 这是一个完整的例子:

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

我认为这应该正确处理所有情况(日期,ID,......)。

答案 3 :(得分:1)

这是我做的方式,跳过mongodb _id条目。

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

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

答案 4 :(得分:1)

怎么样?

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

有关BsonDocument的列表

bsonDocList.ConvertAll(BsonTypeMapper.MapToDotNetValue)

答案 5 :(得分:1)

我的问题与DotNet Core WebAPI如何将对象序列化为json有关。如果从格式化为json的方法返回字符串,则WEBAPI会再次将其序列化为json。仅当您使用通用BsonDocument将其保存到MongoDb时才需要。

[HttpGet()]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<string>> GetAsync()
{
    return Ok(ret.ToJson());
}

修复

[HttpGet()]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<object>> GetAsync()
{
    var doc = await _collection.Find(...).FirstOrDefaultAsync();
    return Ok(JObject.Parse(doc.ToJson()));
}

答案 6 :(得分:1)

通过实验,我发现有一个选项可以使此方法输出正确的JSON:

BsonDocument myBsonDocument = ... //code that loads a BSON document
myBsonDocument.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.RelaxedExtendedJson})

结果:

{ "_id" : { "$oid" : "5fb7a33e73152101d6610e9d" }, "moreProperties" : "moreValues" }

答案 7 :(得分:0)

如果您需要在返回具有BsonDocument的模型以添加动态数据时需要使用此ASP.NET Core。您可以根据MarkKGreenway的答案使用此JsonConverter实现!

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

然后在您的Startup.cs中添加以下内容。

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

答案 8 :(得分:0)

关于

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

答案 9 :(得分:0)

如果BSON文档的内容另存为,

System.setProperty

}

然后与通用类一起使用。

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

答案 10 :(得分:0)

由于 Davide Icardi 答案已被弃用,所以:

  1. 安装Newtonsoft.Json.Bson package
  2. BsonReader 替换为 BsonDataReader

你的扩展方法应该是这样的:

using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using System.IO;
using System.Text;

namespace YourNamespaceGoesHere
{
    public static class BsonHelpers
    {
        public static string ToNormalJson(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 BsonDataReader(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();
                }
            }

        }

    }
}

这应该会生成您正在寻找的预期的正常有效 JSON 字符串 :)