2011-10-19 21 views
20

私はARCGis Webサービスをいくつか消費していますが、残念なJSONデザインがあります。例えば、彼らはこのような何か与えるかもしれない:今すぐJSON.NET - 条件付きタイプ逆シリアル化

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

を、渡されたgeometryType値に応じて、ジオメトリオブジェクトは、いくつかの異なるオブジェクトタイプのものであってもよいです。上記の場合、ジオメトリノードのタイプはです。ポリゴンです。

ですので、質問です。 JSON.NETでは、この条件付きタイピングを通知する方法はありますか?もしそうでないなら、上記のオブジェクト情報に基づいて、ジオメトリノードをデシリアライズするプロバイダを構築する方法はありますか?そうでない場合は、これを解決するための推奨方法がありますか?

編集:私は、カスタムコンバータを構築するにはかなり広範囲に見えたが、コンバータでの問題は、彼らがこの抽象メソッドを持っているということです。

public override T Create (Type objectType) 

しかし、私はここで作成するためにどのような種類を知る方法はありません上記のJSONで指定されたオブジェクトの種類を知る必要があります。

ありがとうございました!

答えて

9

サンプルコンバータを組み合わせて、正しい方向に向けることができます。ここに私のサンプルJSON文字列は以下のとおりです。

{geometryType: "esriGeometryPolygon"、ジオメトリ:{リング:5}}

{geometryType: "esriGeometryOther"、ジオメトリ:{リング:5}}

私はこのようにそれをテストした:

012:

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

は、私は同様の問題を抱えていたとJsonSchemaYuval Itzchakovさんのおかげで助けを借りて、それを解決:

// 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; 
    } 
:それはそのような何かのように見えます Deserialize json in a “TryParse” way

関連する問題