Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use with MongoDB #99

Open
fredgate opened this issue Feb 10, 2018 · 9 comments
Open

Use with MongoDB #99

fredgate opened this issue Feb 10, 2018 · 9 comments

Comments

@fredgate
Copy link

This library is nice, but we can not easily use classes like Point, MultiPoints... in our POCO mapped to MongoDB document.
Imagine a document like that :

{
  "_id": "5a7b8a6f70217a0c44b0ecaa",
  "name": "Foo",
  "position": {
    "type": "Point",
    "coordinates": ["2.879", "45.5931"]
  }
}

Deserialization of document by C# MongoDB driver fails because it cannot deserialize the position embedded document as the type field does not exists in the Point class : there is no type attribute, neither setter for Type property.
Error message is :
FormatException: An error occurred while deserializing the Position property of class MyProject.MyClass : Element 'type' does not match any field or property of class GeoJSON.Net.Geometry.Point.

Can we consider to have a private setter on Type property. The property could be available in the abstract base class GeoJSONObject, and its constructor could take the type as parameter and set it.

public abstract class GeoJSONObject : ...
{
  public GeoJSONObject(GeoJSONObjectType type)
  {
    this.Type = type;
  }

  public GeoJSONObjectType Type { get; private set }
  .....
}

So geometry classes could be simplified like this :

public class Point : GeoJSONObject, ...
{
  public Point(IPosition coordinates) : base(GeoJSONObjectType.Point)
  {
    this.Coordinates = coordinates ?? throw new ArgumentNullException(nameof(coordinates));
  }

  // This property is already available in base class
  // public override GeoJSONObjectType Type => GeoJSONObjectType.Point;

  ....
}

What do you think ?

@matt-lethargic
Copy link
Member

Hi, this sounds like an issue with how the Mongo driver does deserialization. I'm no Mongo expert, but I'm guessing that the driver doesn't use Json.Net under the hood which this library as built for.

I just tried this:

var json = "{\"name\":\"bob\",\"number\":234324, \"location\": {\"coordinates\":[90.65464646,53.2455662],\"type\":\"Point\"}}";
var test = JsonConvert.DeserializeObject<TestIt>(json);

using a POCO

internal class TestIt
{
    public string Name { get; set; }
    public int Number { get; set; }
    public Point Location { get; set; }
}

and it works with no issues.

@matt-lethargic
Copy link
Member

Hi @fredgate , did you get anywhere with this? Is there any help I can offer?

@101SYS
Copy link

101SYS commented Jun 3, 2018

Cannot save Polygon to MongoDB 3.6. Using latest GeoJSON.Net version, available today. Any suggestions?

@antonsimola
Copy link

antonsimola commented Jun 6, 2018

I'm struggling with this as well. I'm experimenting registering class maps (BsonClassMap.RegisterClassMap) for each relevant class in GeoJSON.NET package.

I would like to have House come through WebAPI and serialize it straight like that into MongoDB:

class House { public Point Location {get;set;}; }

However some fields such as type and coordinates are not being stored in Mongodb.

EDIT: ended up writing my own POCOs for GeoJSON. If I tried using MongoDB C# driver provided GeoJSON, WebAPI wouldn't work. With these, Mongo serialization wouldn't work.

@darbio
Copy link

darbio commented Feb 21, 2019

@antonsimola same issue here. Would you be able to share your POCOs to save reincarnation on my end?

@matt-lethargic
Copy link
Member

Hi @fredgate, @antonsimola and @darbio, I looked at this back when the issue was first opened. I did start looking at a Contrib library "GeoJSON.Net.Contrib.MongoDB" thats was my idea anyway. I remember that I was finding it hard working out how the c# driver worked. Now I have some time I will have another look. Any help or code examples would be great, think getting something working for Mongodb would be an advantage

@willoftw
Copy link

willoftw commented Nov 6, 2020

Encountering this issue also, maybe due to too many levels of nesting? (we are using quite big documents)
EDIT: It isnt, tried just putting a FeatureCollection straight into mongo without luck

@jonyboom
Copy link

jonyboom commented Apr 26, 2021

After getting stuck on this myself here is my solution.

public class MultiPolygonSerializer : SerializerBase<Feature<MultiPolygon>>
{
    public override Feature<MultiPolygon> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bson = BsonDocumentSerializer.Instance.Deserialize(context);
        return JsonConvert.DeserializeObject<Feature<MultiPolygon>>(bson.ToJson());
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Feature<MultiPolygon> value)
    {
        if (value is not null)
        {
            var json = JsonConvert.SerializeObject(value);
            BsonDocumentSerializer.Instance.Serialize(context, args, BsonDocument.Parse(json));
        }
    }
}
public class ObjectToBePersistedToMongo
{
    [BsonSerializer(typeof(MultiPolygonSerializer))]
    public Feature<MultiPolygon> OpportunityPerimeter { get; set; }
}

Or of couse you can use a class map instead of an attribute

BsonClassMap.RegisterClassMap<ObjectToBePersistedToMongo>(map =>
{
    map.AutoMap();
    map.GetMemberMap(c => c.OpportunityPerimeter).SetSerializer(new MultiPolygonSerializer());
});

@wassim-k
Copy link

For those still looking for a solution, I have created a MongoDB.NetTopologySuite.Serialization package which adds support for serializing/deserializing NetTopologySuite models to BSON and back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants