Reputation: 590
I have an issue with the MongoDB driver. I'm writing a .Net Core web api that is consumed by a JavaScript frontend. There is a Parent
and Child
class. In the child class I wanted to implement a weakly typed field where I could put in any JSON
value, just a regular key/value store. That's my setup:
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; }
}
In the database a parent element may look as follows:
{
"_id" : 1,
"Children" : [
{
"_id" : 1,
"Type" : "TEXT",
"Properties" : {
"Width" : 100,
"Height" : 100,
"Color" : "red"
}
}]
}
The reading from the database is working that way. MongoDB is deserializing the data and everything is ok. The issue I have is on the controller level. That's the fairly simple Controller code:
[HttpGet]
public ActionResult<List<Parent>> Get()
{
// _parentRepository.Get() is returning a List<Parent> read from the DB
return _parentRepository.Get();
}
But when I send a request to the API that's the result I'm getting:
{
"id" : 1,
"children" : [
{
"id" : 1,
"type" : "TEXT",
"properties" : [
{
"name": "Width",
"value": 100
},
{
"name": "Height",
"value": 100
},
{
"name": "Color",
"value": "red"
}
]
}]
}
So as you can see the BsonDocument
is serialized like a dictionary where it's a list of key/value pairs. I would prefer to have a flat JSON there, so a representation exactly like in the database.
I tried with JsonResult
and an explicit cast to Controller.Json()
, but the result was the same.
NOTE: I'm using .NET Core 2.2
! I know 3.0 has introduced some changes related to JSON, but haven't been able to update the project yet.
Thanks!
Upvotes: 1
Views: 362
Reputation: 49985
This is just the way Newtonsoft.Json
serializes BsonDocument
type into string
. You can easily fix that introducing your own serializer and running BsonDocument.ToJson()
method:
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());
}
}
And decorating your type:
public class Child
{
public int Id { get; set; }
public string Type { get; set; }
[JsonConverter(typeof(BsonToJsonConverter))]
public BsonDocument Properties { get; set; }
}
Upvotes: 2