Сериализация слабо типизированного BsonDocument в JSON в контроллере - PullRequest
1 голос
/ 07 октября 2019

У меня проблема с драйвером MongoDB. Я пишу веб-API .Net Core, который используется интерфейсом JavaScript. Существует класс Parent и Child. В дочернем классе я хотел реализовать поле со слабой типизацией, в которое я мог бы поместить любое значение JSON, просто обычное хранилище ключей / значений. Вот мои настройки:

public class Child
{
    public int Id { get; set; }

    public string Type { get; set; }

    public BsonDocument Properties { get; set; }
}
public class Parent
{
   [BsonId]
   [BsonRepresentation(BsonType.ObjectId)]
   public string Id { get; set; }

   public List<Child> Children { get; set; }
}

В базе данных родительский элемент может выглядеть следующим образом:

{
    "_id" : 1,
    "Children" : [
    {
        "_id" : 1,
        "Type" : "TEXT",
        "Properties" : {
            "Width" : 100,
            "Height" : 100,
            "Color" : "red"
        }
   }]
}

Чтение из базы данных работает таким образом. MongoDB десериализует данные, и все в порядке. У меня проблема на уровне контроллера. Это довольно простой код контроллера:

[HttpGet]
public ActionResult<List<Parent>> Get()
{
   // _parentRepository.Get() is returning a List<Parent> read from the DB
   return _parentRepository.Get();
}

Но когда я отправляю запрос API, вот результат, который я получаю:

{
    "id" : 1,
    "children" : [
    {
        "id" : 1,
        "type" : "TEXT",
        "properties" : [
            {
                "name": "Width",
                "value": 100
            },
            {
                "name": "Height",
                "value": 100
            },
            {
                "name": "Color",
                "value": "red"
            }
       ]

   }]
}

Итак, как вы можете видеть BsonDocument сериализуется как словарь, где это список пар ключ / значение. Я бы предпочел иметь плоский JSON, поэтому представление точно такое же, как в базе данных.

Я пробовал с JsonResult и явным приведением к Controller.Json(), но результат был таким же.

ПРИМЕЧАНИЕ: я использую .NET Core 2.2! Я знаю, что 3.0 внес некоторые изменения, связанные с JSON, но пока не смог обновить проект.

Спасибо!

1 Ответ

2 голосов
/ 07 октября 2019

Это просто способ Newtonsoft.Json сериализует BsonDocument тип в string. Вы можете легко это исправить, представив свой собственный сериализатор и запустив метод BsonDocument.ToJson():

public class BsonToJsonConverter : JsonConverter<BsonDocument>
{
    public override BsonDocument ReadJson(JsonReader reader, Type objectType, BsonDocument existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        return BsonDocument.Parse(token.ToString());
    }

    public override void WriteJson(JsonWriter writer, BsonDocument value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value.ToJson());
    }
}

И украсив свой тип:

public class Child
{
    public int Id { get; set; }

    public string Type { get; set; }

    [JsonConverter(typeof(BsonToJsonConverter))]
    public BsonDocument Properties { get; set; }
}
...