2012-06-11 14 views
6

私は、数に応じて、配列またはオブジェクトとしてプロパティを返す外部APIを使用しています。これを処理する良い方法は何ですか?非配列JSONオブジェクトをJson.netの配列として解析します。

配列として返す:

{ 
    "contacts": { 
     "address": [ 
      { 
       "id": "47602070", 
       "type": "Work", 
       "street": "MyStreet", 
       "city": "MyCity", 
       "zip": "12345", 
       "country": "USA" 
      }, 
      { 
       "id": "47732816", 
       "type": "GPS", 
       "street": "50.0,30.0" 
      } 
     ] 
    } 
} 

をオブジェクトとして返す:

{ 
    "contacts": { 
     "address": { 
      "id": "47602070", 
      "type": "Work", 
      "street": "MyStreet", 
      "city": "MyCity", 
      "zip": "12345", 
      "country": "USA" 
     } 
    } 
} 

私はカスタムデシリアライザを使用し、長さ1の配列を返すようになり、回避策を考えていますオブジェクトの場合と、配列の場合のデフォルトのデシリアライゼーションがありますが、まだそれを行う方法はわかりません。

オブジェクトを配列にデシリアライズしてみましたが、Json.netが私の場合はこのケースを処理することを望んでいましたが、ダイスは処理しないと思っていました。

答えて

3

カスタムJSON.NETコンバータがここでトリックを行うかもしれません。それほど難しいことではありません。

DateTimeプロパティの場合は、次のようにします。問題のプロパティをカスタムコンバータで飾るだけです。

[JsonObject(MemberSerialization.OptIn)] 
public class MyClass 
{ 
    [JsonProperty(PropertyName = "creation_date")] 
    [JsonConverter(typeof(UnixDateTimeConverter))] 
    public DateTime CreationDate { get; set; } 
} 

JSON.NETは配管のほとんどを提供します。基本コンバータから派生しただけです。

public class UnixDateTimeConverter : DateTimeConverterBase 
{ 
    public override void WriteJson(JsonWriter writer, object value, 
            JsonSerializer serializer) 
    { ...} 

    public override void WriteJson(JsonWriter writer, object value, 
            JsonSerializer serializer) 
    { ... } 
} 

あなたがしなければならないのは、ReadJson(直列化復元)とWriteJson(シリアライズ)メソッドを実装しています。

あなたはここに完全な例を見つけることができます:あなたはもう少し制御を必要とする、あなたの特定の問題については

Writing a custom Json.NET DateTime Converter

を。あなたがしてくださいJSONデータを自分で解析し、あなたと連絡先オブジェクト(複数可)を構成することができます上記のようなカスタムコンバータを使用して

public class Contact 
{ 
    private List<Address> _addresses = new List<Address>();  
    public IEnumerable<Address> Addresses { get { return _addresses; } 
} 

public class ContactConverter : CustomCreationConverter<Contact> 
{ 
    public override Contact Create(Type objectType) 
    { 
     return new Contact(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object 
     existingValue, JsonSerializer serializer) 
    { 
     var mappedObj = new Contact(); 

     // Parse JSON data here 
     // ... 

     return mappedObj; 
    } 
} 

:コンバータの以下のタイプを試してみてください。 desearilizing時にカスタムコンバータを渡す必要があり、この場合

JSON.NET Custom Converters–A Quick Tour

は、私はここで見つける例を変更しました。

Contact contact = 
    JsonConvert.DeserializeObject<Contact>(json, new ContactConverter()); 
+0

徹底した入力をありがとう。あなたの例から私はそれを働かせて、最終結果を投稿しました。 – angularsen

+0

あなたが少なくともコメントする理由をdownvoteしたら...ヒットして実行しないでください –

+0

リンクをありがとう。 :) –

5

Christophe Geersのanswerに基づいて、私がやったことがここにあります。

  1. 常にJSONを配列として解析するためのカスタムJSONコンバータを作成します。 JSONが配列以外のオブジェクトの場合は、オブジェクトを逆シリアル化して配列にラップします。

  2. 対応するプロパティをカスタムコンバータ属性でマークします。

カスタムコンバータ

public class JsonToArrayConverter<T> : CustomCreationConverter<T[]> 
{ 
    public override T[] Create(Type objectType) 
    { 
     // Default value is an empty array. 
     return new T[0]; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object 
     existingValue, JsonSerializer serializer) 
    { 

     if (reader.TokenType == JsonToken.StartArray) 
     { 
      // JSON object was an array, so just deserialize it as usual. 
      object result = serializer.Deserialize(reader, objectType); 
      return result; 
     } 
     else 
     { 
      // JSON object was not an arry, so deserialize the object 
      // and wrap it in an array. 
      var resultObject = serializer.Deserialize<T>(reader); 
      return new T[] {resultObject}; 
     } 
    } 
} 

質問例えばデータ構造

public class Organisation 
{ 
    public Contacts contacts; 
} 

public class Address 
{ 
    public string id; 
    public string street; 
    public string city; 
    public string type; 
    public string zip; 
    public string country; 
} 

public class Contacts 
{ 
    // Tell JSON.net to use the custom converter for this property. 
    [JsonConverter(typeof(JsonToArrayConverter<Address>))] 
    public Address[] address; 
} 
1

注:代わりにCustomCreationConverterを使用しての、あなただけの普通のコンバータを使用することができます。たとえば、私は次のようなものを使用します:

関連する問題