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

在C中将MongoDB BsonDocument转换为有效的JSON#,json,mongodb,mongodb-.net-driver,Json,Mongodb,Mongodb .net Driver,我正在与MongoDB C#驱动程序合作。我有一个BsonDocument,其中包含一些数据,其中包括一些MongoDB特定的类型(如objectid和ISODates)。我想将其转换为有效的通用JSON字符串。换句话说,我不能有像\u id:ObjectId(…)或日期:ISODate(…)这样的东西,但我更喜欢\u id:“…”和日期:“…”。基本上,我想将这些只有MongoDB才能识别的特殊类型转换为常规字符串,以便更容易地解析它们。问题是像.ToJson()(另一个StackOverfl

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

我大部分时间都在使用


大多数情况下,这会起作用。如果需要,您可以设置一些JsonSerializerSettings

我遇到了同样的问题,您可以通过以下方式获得有效的JSON:

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

我仍在试图找到一种方法来平复它。

我就是这样做的,跳过mongodb\u 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();
var collection=\u database.GetCollection(“测试”);
var result=await collection.Find(new BsonDocument())
.Project(Builders.Projection.Exclude(“\u id”))
.ToListAsync();
var obj=result.ToJson();

在我看来,最好的选择是使用
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等)。

如果您需要使用此ASP.NET内核,那么您可能会返回一个具有BsonDocument的模型,以便能够添加动态数据。您可以根据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()));
那怎么办

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

如果BSON文档的内容保存为,则如下

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

然后它与泛型类一起工作

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

    }
私有静态T进程BSONVERSION(BsonDocument数据)
{
var content=data.GetElement(“_v”);
var jsonDataContent=content.Value.AsBsonValue.ToJson();
返回Newtonsoft.Json.JsonConvert.DeserializeObject(jsonDataContent);
}
MongoDB.Bson(2.5+)支持在BsonValues和.Net对象之间映射。

要将BsonValue(或BsonDocument)映射到.Net对象,请使用

var dotNetObj = BsonTypeMapper.MapToDotNetValue(bsonDoc);
然后可以使用您选择的序列化库。比如说,

JsonConvert.SerializeObject(dotNetObj);
如果您有一个B文档列表

var dotNetObjList = bsonDocList.ConvertAll(BsonTypeMapper.MapToDotNetValue);

我的问题与DotNet Core WebAPI如何将对象序列化为json有关。如果从格式化为json的方法返回字符串,WEBAPI将再次将其序列化为json。只有在使用一般BsonDocument保存到MongoDb时,才需要此选项

[HttpGet()]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<string>> GetAsync()
{
    return Ok(ret.ToJson());
}
[HttpGet()]
[产品响应类型(StatusCodes.Status200OK)]
公共异步任务GetAsync()
{
返回Ok(ret.ToJson());
}
修理

[HttpGet()]
[产品响应类型(StatusCodes.Status200OK)]
公共异步任务GetAsync()
{
var doc=await_collection.Find(…).FirstOrDefaultAsync();
返回Ok(JObject.Parse(doc.ToJson());
}

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

BsonDocument myBsonDocument=//加载BSON文档的代码
ToJson(新的JsonWriterSettings{OutputMode=JsonOutputMode.RelaxedExtendedJson})
结果:

{“\u id”:{“$oid”:“5fb7a33e73152101d6610e9d”},“moreProperties”:“moreValues”}
由于答案已被弃用,因此:

  • 安装
  • BsonReader
    替换为
    BsonDataReader
  • 您的扩展方法应如下所示:

    使用MongoDB.Bson;
    使用MongoDB.Bson.IO;
    使用MongoDB.Bson.Serialization;
    使用Newtonsoft.Json;
    使用Newtonsoft.Json.Bson;
    使用System.IO;
    使用系统文本;
    命名空间YourNamespaceGoesher
    {
    公共静态类BsonHelpers
    {
    公共静态字符串到normaljson(BsonDocument bson)
    {
    使用(var stream=new MemoryStream())
    {
    使用(var writer=newbsonbinarywriter(流))
    {
    序列化(writer,typeof(BsonDocument),bson);
    }
    stream.Seek(0,SeekOrigin.Begin);
    使用(var reader=newbsondatareader(流))
    {
    var sb=新的StringBuilder();
    var sw=新的StringWriter(sb);
    使用(var jWriter=newjsontextwriter(sw))
    {
    jWriter.DateTimeZoneHandling=DateTimeZoneHandling.Utc;
    jWriter.WriteToken(reader);
    }
    使某人返回字符串();
    }
    }
    }
    }
    }
    

    这将生成所需的正常有效JSON字符串:)

    你运气好吗?Troll spotted:@MatthewJamesDavis我最终不得不手动定义一个类来反序列化。基本上->使用Mongo驱动程序fns反序列化到类中,然后序列化对象。。。JsonConvert.SerializeObject(BsonSerializer.Deserialize(doc))。这里的每一行都是一个潜在的bug。。MarkKGreenway提供了一个超级简单的e-one班轮,正如预期的那样工作@普姆金如果
    var dotNetObjList = bsonDocList.ConvertAll(BsonTypeMapper.MapToDotNetValue);
    
    [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()));
    }