【问题标题】:JSON.NET - Conditional Type DeserializationJSON.NET - 条件类型反序列化
【发布时间】:2011-10-19 05:08:06
【问题描述】:

我正在使用一些 ARCGis Web 服务,它们有一些不幸的 JSON 设计。例如,他们可能会给出如下内容:

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

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

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

编辑:我对构建自定义转换器进行了相当广泛的研究,但转换器的问题在于他们有这个抽象方法:

public override T Create (Type objectType)

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

谢谢!

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    我整理了一个示例转换器,为您指明正确的方向。这是我的示例 JSON 字符串:

    {geometryType:“esriGeometryPolygon”,几何:{环:5}}

    {geometryType:“esriGeometryOther”,几何:{环: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; }
    }
    

    【讨论】:

    • JSON 是无序的。不能保证类型会是第一个属性,甚至不能保证它会在子对象之前
    【解决方案2】:

    我遇到了类似的问题,并通过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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 2011-09-19
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多