我正在使用一些ARCGis Web服务,他们有一些不幸的JSON设计。例如,他们可能会这样:
{
geometryType: "esriGeometryPolygon"
geometry: {
-rings: [
-[.blah..... }}
现在,根据传入的 geometryType 值, geometry 对象可能是几种不同对象类型之一。在上面的例子中,几何节点的类型为 Polygon 。
所以,问题是;在JSON.NET中有没有办法记录这种条件类型?如果没有(我怀疑有),有没有办法根据上面的对象信息构建一个反序列化 geometry 节点的提供程序?如果没有,有没有推荐的解决方法?
编辑:我看起来非常广泛地构建自定义转换器,但转换器的问题是它们有这种抽象方法:
public override T Create (Type objectType)
但是,我无法知道在这里创建什么类型,我需要知道上面的JSON中指定了什么类型的对象。
谢谢!
答案 0 :(得分:12)
我将一个样本转换器放在一起,指向正确的方向。以下是我的示例JSON字符串:
{geometryType:“esriGeometryPolygon”,geometry:{rings:5}}
{geometryType:“esriGeometryOther”,geometry:{rings:5}}
我测试了这样:
var serializer = new JsonSerializer();
var geometry = serializer.Deserialize<Geometry>(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; }
}
答案 1 :(得分:0)
我遇到了类似的问题,并使用JsonSchema
解决了问题,感谢Yuval Itzchakov的帮助:Deserialize json in a “TryParse” way
它看起来像那样:
// 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<Error>.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;
}