JSON.NET – 条件类型反序列化

我正在使用一些ARCGis Web服务,他们有一些不幸的JSON设计。 例如,他们可能会给出这样的东西:

{ geometryType: "esriGeometryPolygon" geometry: { -rings: [ -[.blah..... }} 

现在,根据传入的geometryType值, 几何对象可以是几种不同对象类型之一。 在上面的例子中,几何节点是Polygon类型。

所以,问题是; 在JSON.NET中有没有办法记录这种条件类型? 如果不是(我怀疑有),有没有办法根据上面的对象信息构建一个反序列化该几何节点的提供程序? 如果没有,有什么建议的解决方法吗?

编辑:我看起来非常广泛地构建自定义转换器,但转换器的问题是他们有这种抽象方法:

 public override T Create (Type objectType) 

但是,我无法知道在这里创建什么类型,我需要知道上面的JSON中指定了什么类型的对象。

谢谢!

我把一个样本转换器放在一起指向正确的方向。 以下是我的示例JSON字符串:

{geometryType:“esriGeometryPolygon”,geometry:{rings:5}}

{geometryType:“esriGeometryOther”,geometry:{rings:5}}

我测试了这样:

 var serializer = new JsonSerializer(); var geometry = serializer.Deserialize(new JsonTextReader(new StringReader(jsonData))); //Should have correctly typed instance here... 

这里是转换器和示例几何对象:

 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; } } 

由于Yuval Itzchakov的帮助,我有一个类似的问题并用JsonSchema解决了它: 用“TryParse”方式反序列化json

它看起来像这样:

  // Check json schema : const string errorJsonSchema = @"{ 'type': 'object', 'properties': { 'error': {'type':'object'}, 'status': {'type': 'string'}, 'code': {'type': 'string'} }, 'additionalProperties': false }"; JsonSchema schema = JsonSchema.Parse(errorJsonSchema); JObject jsonObject = JObject.Parse(jsonResponse); if (!jsonObject.IsValid(schema)) { error = null; return false; } // Try to deserialize : try { error = new JsonSerializer.DeserializeFromString(jsonResponse); return true; } catch { // The JSON response seemed to be an error, but failed to deserialize. // This case should not occur... error = null; return false; }