Tengo un problema con el controlador MongoDB. Estoy escribiendo una api web .Net Core que es consumida por una interfaz de JavaScript. Hay una clase Parent y Child. En la clase secundaria, quería implementar un campo de tipo débil donde pudiera ingresar cualquier valor JSON, solo un almacén de clave / valor normal. Esa es mi configuración:

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

En la base de datos, un elemento padre puede tener el siguiente aspecto:

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

La lectura de la base de datos funciona de esa manera. MongoDB está deserializando los datos y todo está bien. El problema que tengo está en el nivel del controlador. Ese es el código de controlador bastante simple:

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

Pero cuando envío una solicitud a la API, ese es el resultado que obtengo:

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

   }]
}

Como puede ver, el BsonDocument está serializado como un diccionario donde es una lista de pares clave / valor. Preferiría tener un JSON plano allí, por lo que una representación exactamente como en la base de datos.

Intenté con JsonResult y una conversión explícita a Controller.Json(), pero el resultado fue el mismo.

NOTA: ¡Estoy usando .NET Core 2.2! Sé que 3.0 ha introducido algunos cambios relacionados con JSON, pero aún no he podido actualizar el proyecto.

¡Gracias!

1
losik123 7 oct. 2019 a las 01:25

1 respuesta

La mejor respuesta

Esta es solo la forma en que Newtonsoft.Json serializa el tipo BsonDocument en string. Puede solucionarlo fácilmente introduciendo su propio serializador y ejecutando el método 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());
    }
}

Y decorando tu tipo:

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

    public string Type { get; set; }

    [JsonConverter(typeof(BsonToJsonConverter))]
    public BsonDocument Properties { get; set; }
}
2
mickl 6 oct. 2019 a las 23:45