Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

c# - JSON.NET - Conditional Type Deserialization

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...