I'm consuming some ARCGis web services, and they have some unfortunate JSON design. for example, they might give something like this:
{ geometryType: "esriGeometryPolygon" geometry: { -rings: [ -[.blah..... }}
Now, depending on the geometryType value passed in, the geometry object may be one of several different object types. in the case above, the geometry node is of type Polygon.
so, question is; in JSON.NET is there any way to notate this conditional typing? if not (which i doubt there is), is there a way to build a provider for deserializing that geometry node, based on the object info above? if not, are there any recommended ways for solving this?
edit: i looked pretty extensively into building a custom converter, but the problem with the converter is that they have this abstract method:
public override T Create (Type objectType)
however, i have no way of knowing what type to create here, i need to know what kind of object was specified in the JSON above.
thanks!
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.
Serialization is the process of converting . NET objects such as strings into a JSON format and deserialization is the process of converting JSON data into . NET objects.
Newtonsoft. Json uses reflection to get constructor parameters and then tries to find closest match by name of these constructor parameters to object's properties. It also checks type of property and parameters to match. If there is no match found, then default value will be passed to this parameterized constructor.
I put together a sample converter to point you in the right direction. Here are my sample JSON strings:
{geometryType: "esriGeometryPolygon", geometry: { rings: 5 } }
{geometryType: "esriGeometryOther", geometry: { rings: 5 } }
I tested it like this:
var serializer = new JsonSerializer(); var geometry = serializer.Deserialize<Geometry>(new JsonTextReader(new StringReader(jsonData))); //Should have correctly typed instance here...
And here is the converter and sample geometry objects:
public class GeometryConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; reader.Read(); // startobject //we should be at geometry type property now if ((string)reader.Value != "geometryType") throw new InvalidOperationException(); reader.Read(); //propertyName var type = (string)reader.Value; Geometry value; switch(type) { case "esriGeometryPolygon": value = new PolygonGeometry(); break; case "esriGeometryOther": value = new OtherGeometry(); break; default: throw new NotSupportedException(); } reader.Read(); // move to inner object property //should probably confirm name here reader.Read(); //move to inner object serializer.Populate(reader, value); reader.Read(); //move outside container (should be end object) return value; } public override bool CanConvert(Type objectType) { return typeof(Geometry).IsAssignableFrom(objectType); } } [JsonConverter(typeof(GeometryConverter))] public class OtherGeometry : Geometry { } [JsonConverter(typeof(GeometryConverter))] public class PolygonGeometry : Geometry { } [JsonConverter(typeof(GeometryConverter))] public class Geometry { public int rings { get; set; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With