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

bry*_*ich 22 c# json.net

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

{
geometryType: "esriGeometryPolygon"
geometry: {
-rings: [
-[.blah..... }}
Run Code Online (Sandbox Code Playgroud)

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

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

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

public override T Create (Type objectType)
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Pau*_*yng 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...
Run Code Online (Sandbox Code Playgroud)

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

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; }
}
Run Code Online (Sandbox Code Playgroud)