it-source

C#에서 MongoDB Bson 문서를 유효한 JSON으로 변환

criticalcode 2023. 6. 25. 20:10
반응형

C#에서 MongoDB Bson 문서를 유효한 JSON으로 변환

저는 몽고DBC# 드라이버로 작업하고 있습니다.나는 있습니다BsonDocument 유형: : Object)이 포함된 ID 및 ISO 짜 ).저는 이것을 유효한 범용 JSON 문자열로 변환하고 싶습니다.다시말해서, 나그것가수없다질습니을 같은 것을 가질 수 ._id: ObjectId(...)또는date: ISODate(...)하지만 더 선호할 것입니다._id: "..."그리고.date: "..."기본적으로 MongoDB만 인식하는 특수 유형을 일반 문자열로 변환하여 보다 쉽게 구문 분석할 수 있도록 하고 싶습니다.와 같은 내장 이 있다는 것입니다..ToJson()(다른 StackOverflow 답변에서 제안하는 바와 같이) 문서가 이러한 특수 유형을 유지 관리하기 때문에 문서를 유효한 JSON으로 변환하지 않습니다.또한 내 문서에는 많은 수준의 배열과 하위 문서가 포함되어 있으므로 단순한 루프로는 충분하지 않습니다.변환하는 가장 좋은 방법은 무엇입니까?BsonDocument이 문제를 피할 수 있을까요?모든 문제를 해결하기 위해 문서를 수동으로 반복하는 것보다 내장된 것을 선호합니다.

몽고DB.Bson(2.5+)은 BsonValues와 사이의 매핑을 지원합니다.넷 객체.BsonTypeMapper 클래스

BsonValue(또는 BsonDocument)를 에 매핑합니다.순 객체 사용

var dotNetObj = BsonTypeMapper.MapToDotNetValue(bsonDoc);

그런 다음 선택한 직렬화 라이브러리를 사용할 수 있습니다.예를들면,

JsonConvert.SerializeObject(dotNetObj);

Bson 문서 목록이 있는 경우

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

저도 같은 일을 당했습니다. 다음을 통해 유효한 JSON을 얻을 수 있습니다.

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

그러나 다음과 같은 것이 반환됩니다.

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

저는 여전히 그것을 납작하게 만드는 방법을 찾고 있습니다.

에 가장 은 제생에가좋방것사다입니용는하법은은장을 사용하는 것입니다.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 등)를 올바르게 처리해야 합니다.

대부분의 시간을 내가 사용해, Json.NET

JsonConvert.SerializeObject(obj); 

대부분의 시간 동안 그것은 효과가 있습니다.필요한 경우 일부 JsonSerializer 설정을 설정할 수 있습니다.

실험을 통해 저는 이 방법이 적절한 JSON을 출력하도록 하는 옵션이 있다는 것을 발견했습니다.

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

결과:

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

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

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

    }

제 문제는 DotNet Core WebAPI가 json에 객체를 직렬화하는 방법과 관련이 있습니다.json으로 포맷된 메서드에서 문자열을 반환하면 WEBAPI는 이 문자열을 json으로 다시 직렬화합니다.일반 Bson Document로 작업하여 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()));
}

David Icardi 답변이 더 이상 사용되지 않기 때문에 다음과 같습니다.

  1. 패키지 설치
  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 문자열을 생성할 것입니다 :)

동적 데이터를 추가할 수 있도록 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()));

어때

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

언급URL : https://stackoverflow.com/questions/27132968/convert-mongodb-bsondocument-to-valid-json-in-c-sharp

반응형