Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Custom Json Deserializer to create a new object

Tags:

c#

.net

json.net

I have the following class. I am trying to deserialize Json into an array of these LookUpData objects:

 [DataContract]
    public class LookUpData
    {
        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public GeographyPoint Location { get; set; }
    }
}

The Json data looks like this:

{
    "Id": "123",
    "Location": {
      "Latitude": 1,
      "Longitude": -1,
      }
    }
  },

I want to create a custom Json Deserializer so that when reading the Json and hits 'Location', it will create a new GeographyPoint type at that moment, from the Latitude and Longitude values.

I have looked at Newtonsoft's documentation at the Custom Json Serializer as well as helpful answers on Stack Overflow such as this one Custom Deserialization using Json.NET already, but I can't find an example of how to actually create a new type when deserializing. For example the error I receive at the moment using the standard deserializer is 'Could not create an instance of type Microsoft.Spatial.GeographyPoint. Type is an interface or abstract class and cannot be instantiated".

I'd be grateful if anyone could please point me in the right direction here. Thanks!

like image 771
Jordan1993 Avatar asked Mar 03 '26 15:03

Jordan1993


1 Answers

You can write a simple JsonConverter for the GeographyPoint type as shown below. This implementation uses a JObject as a means to easily read from (and write to) the JSON. The key to creating the GeographyPoint instance is using the static Create method provided by that type.

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken obj = JToken.Load(reader);
        if (obj.Type == JTokenType.Null) return null;
        double latitude = (double)obj["Latitude"];
        double longitude = (double)obj["Longitude"];
        return GeographyPoint.Create(latitude, longitude);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        GeographyPoint point = (GeographyPoint)value;
        JObject obj = new JObject(
            new JProperty("Latitude", new JValue(point.Latitude)),
            new JProperty("Longitude", new JValue(point.Longitude))
        );
        obj.WriteTo(writer);
    }
}

To use the converter, just add a [JsonConverter] attribute to the Location property in your LookUpData class:

public class LookUpData
{
    public string Id { get; set; }

    [JsonConverter(typeof(GeographyPointConverter))]
    public GeographyPoint Location { get; set; }
}

Note: you don't actually need the [DataContract] and [DataMember] attributes when using Json.Net, unless you need opt-in semantics — meaning you need to specifically identify which classes and members are included in serialization and deserialization. If these attributes are omitted, then all classes and members are included by default, which seems to be your intent here.

Working demo: https://dotnetfiddle.net/YNo1vP

like image 55
Brian Rogers Avatar answered Mar 06 '26 03:03

Brian Rogers



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!