1

I'm trying to deserialize a Geoposition Object in my Windows Phone (WinRT) App but getting this Exception:

-2146233088 with Message: "Unable to find a constructor to use for type Windows.Devices.Geolocation.Geoposition. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'CivicAddress'".

Is Geoposition not compatible with Newtonsoft Json.NET? If it is not, I could use some help in finding a workaround.

The code snippet below shows where the exception is thrown.

public async void Sample()
{    
    Geolocator geo = new Geolocator();
    geo.DesiredAccuracyInMeters = 50;
    var x = await geo.GetGeopositionAsync();
    Geoposition geo = JsonConvert.DeserializeObject<Geoposition>(CurrentContext.LocationAsString);
    await EventMap.TrySetViewAsync(geo.Coordinate.Point, 18D);
}
fantaseador
  • 99
  • 2
  • 9
  • `fing a constructor`? find, perhaps? – Marc B Apr 09 '15 at 19:11
  • Where do I put it even if I find it? Neither is Geoposition editable nor is JsonConvert – fantaseador Apr 09 '15 at 19:29
  • In the future, instead of pasting in an image type the code down. It's easier for others to copy it and to try it. – PiotrWolkowski Apr 09 '15 at 19:57
  • Geoposition x = JsonConvert.DeserializeObject(CurrentContext.LocationAsString); – fantaseador Apr 09 '15 at 20:16
  • You can either create a proxy (sub)class, or create your own `JsonConverter`. Similar problem resolved here: https://stackoverflow.com/questions/25471890/deserialize-json-xyz-point. Converter solution is probably better. – dbc Apr 10 '15 at 16:35

1 Answers1

2

It seems like Geoposition only has read-only properties, and no public constructor that takes values for these properties as constructor arguments. So you can serialize it, but not construct it during deserialization.

What you could do as a work-around, is to construct your own version of this class specifically for serialization purposes, including only those properties you actually need in your app.

For example, if as in your question, you only need the Geoposition.Coordinate.Point field to be serialized, you could do the following:

namespace YourAppNameSpaceHere
{
    using Windows.Devices.Geolocation;

    public class SerializableGeoPoint
    {
        public SerializableGeoPoint(Geoposition location) 
            : this(location.Coordinate.Point) {}

        public SerializableGeoPoint(Geopoint point)
        {
            this.AltitudeReferenceSystem = point.AltitudeReferenceSystem;
            this.GeoshapeType = point.GeoshapeType;
            this.Position = point.Position;
            this.SpatialReferenceId = point.SpatialReferenceId;
        }

        [JsonConverter(typeof(StringEnumConverter))]
        public AltitudeReferenceSystem AltitudeReferenceSystem { get; set; }

        [JsonConverter(typeof(StringEnumConverter))]
        public GeoshapeType GeoshapeType { get; set; }

        [JsonProperty]
        public BasicGeoposition Position { get; set; }

        [JsonProperty]
        public uint SpatialReferenceId { get; set; }

        public Geopoint ToWindowsGeopoint()
        {
            return new Geopoint(Position, AltitudeReferenceSystem, SpatialReferenceId);
        }
    }
}

When serializing you can then do:

Geoposition position = ....; // call to get position.
CurrentContext.LocationAsString = JsonConvert
    .SerializeObject(new SerializableGeoPoint(position));

And deserializing as:

var locationPoint = JsonConvert
    .DeserializeObject<SerializableGeoPoint>(CurrentContext.LocationAsString)
    .ToWindowsGeopoint();

You may need to add this for your serialization settings somewhere during application startup, where you perform other one-time initializations for your app.

JsonConvert.DefaultSettings = (() =>
{
    var settings = new JsonSerializerSettings();
    settings.Converters.Add(new StringEnumConverter());
    return settings;
});

It specifies the default settings for JSON serialization, in this case adding the converter that knows how to convert between enums and strings.

Alex
  • 13,024
  • 33
  • 62