3

I have a simple ADO.NET Entity Model which I'm exposing using OData. One of the fields in the entity model is a Geography type (geography in SQL Server). I can query the data just fine, and I get the following serialized format for the geography columns:

"Shape":{
    "WellKnownValue":{
      "CoordinateSystemId":4326,
      "WellKnownText":"POLYGON ((...)",
      "WellKnownBinary":null
    }

So this works, but I'm hoping I can change the serialization of this object to make it more like:

"Shape":"4326:POLYGON((...))"

Admittedly this is mostly for aesthetics, but it'd be nicer to have a simpler graph and shorter message too.

I wrote the following class which I thought would help:

public class JsonGeographyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.Equals(typeof(DbGeography));
    }

    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)
    {
        var geog = (DbGeography)value;
        if (geog != null)
            writer.WriteValue(string.Format("{0}:{1}", geog.WellKnownValue.CoordinateSystemId, geog.WellKnownValue.WellKnownText));
        else
            writer.WriteNull();
    }
}

And added it to the JSON serializer settings in my OData configuration:

var config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new JsonGeographyConverter());

But it doesn't seem to make a difference. In fact, a breakpoint placed in CanConvert is never reached, so I'm inclined to think that I'm not setting up JSON correctly.

I also tried:

var config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new JsonGeographyConverter());

but this also had no effect.

Hopefully someone can point out what I'm doing wrong?

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Barguast
  • 5,926
  • 9
  • 43
  • 73

2 Answers2

1

Although Web API iteself uses the Json.Net serializer, a little digging around in the source code seems to indicate that the MediaTypeFormatter for Web API OData uses its own internal serializer which is not Json.Net. Therefore, adding a Json.Net converter to the configuration will not have any effect on OData. Unfortunately, without a deep-dive analysis of the code, I do not know whether OData's serializer is extensible in the same way, and/or whether it is possible to get it to use Json.Net instead.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • Thanks for this. I had a quick dig through, but I don't see a place I can modify its serialization. I'll try asking on the OData site since it seems to be an issue there. Thanks again. – Barguast Feb 15 '14 at 11:26
0

I required some asthetics as well since I did not want to read into a json object when all I required was the latlng on the client side so I did the same.

My code is below. Been working for awhile now with no issues.

  public class DbGeographyConverter : JsonConverter
{
    public override bool CanConvert ( Type objectType )
    {
        return objectType.IsAssignableFrom( typeof( DbGeography ) );
    }

    public override object ReadJson ( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
    {
        if ( reader.Value == null ) {
            return null;
        }

        return Parser.ToDbGeography( reader.Value.ToString() );
    }

    public override bool CanWrite { get { return true; } }

    public override void WriteJson ( JsonWriter writer, object value, JsonSerializer serializer )
    {
        //Attempting to serialize null dosent go well
        if ( value != null ) {
            var location = value as DbGeography;
            serializer.Serialize( writer, location.Latitude + "," + location.Longitude );
        }
    }
}
Warren
  • 384
  • 4
  • 17
  • Thanks. I don't think this works with OData though - it has its own serializer, and I don't think it is quite as flexible when it comes to custom serialization. – Barguast Aug 11 '15 at 09:29