2013-05-04 3 views
7

私はこの質問のためのstackoverflowに他のいくつかの結果があることを確認しますが、動作していないか、あいまいです。JSON.NETを使用して、時にはオブジェクトであり、時にはオブジェクトの配列である値を処理するにはどうすればよいですか?

問題は、JSONが戻ってきて自分のカスタムタイプの1つにシリアル化されているときに、JSONのビットの1つが配列になることがあります。文字列。カスタムタイプに文字列があり、JSONが配列の場合、エラーが発生します。 JSONがオブジェクトであり、カスタムタイプが配列の場合も同じことが起こります。それをプロパティにマップすることはできません。

私はこれを解決することにしました。私はこの特定のプロパティの非直列化をオーバーライドしたいと思います。それがオブジェクトであれば、それを1オブジェクトの配列に変換したいと思います。

私が連載中のオブジェクトでは、非直列化の方法をオーバーライドすると思われるJsonConverterを追加しました。

[JsonConverter(typeof(ArrayOrSingleObjectConverter<string>))] 
public List<string> person { get; set; } 

カスタムコンバーターは、単一のオブジェクトを配列に変換するという考えがあります。したがって、JSONが "Hello"の場合、文字列をListに変換できないという例外をスローするのではなく、 "Hello"を含むListをPersonに設定します。

既に配列の場合は、それをそのままにしておく必要があります。

コンバータは、次のようになります。

public class ArrayOrSingleObjectConverter<T> : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return true; // Not sure about this but technically it can accept an array or an object, so everything is game. 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (objectType == typeof(List<T>)) 
     { 
      return serializer.Deserialize<List<T>>(reader); 
     } 
     else 
     { 
      var singleObject = serializer.Deserialize<T>(reader); 
      var objectAsList = new List<T>(); 
      objectAsList.Add(singleObject); 
      return objectAsList; 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

それは動作しません。上記のコードでは、単一の文字列を逆シリアル化しようとすると例外がスローされ、if文内のListにキャストできないことが示されています( 'objectype'はListです)。

私は、読み取りと書き込みの方法が何をしているのかを正確に理解するのに苦労しています。 stackoverflowのもう一つの答えでは、readメソッドにNotImplementedExceptionを投げることを示唆しています。しかし、それを行うと、readメソッドが呼び出され、例外がスローされます。

私は正しい軌道に乗っていると思っていますが、正しい方向にナッジが必要です。私は、ReadJSonメソッドが何をしているのか、そのパラメータが何を意味しているのか少し混乱していると思います。

Deserializeメソッド呼び出しで値を指定しなかったため、値がどこから来ているのか分かりません。

私はこの1つの私の深さのビットです。

+0

「変数」オブジェクトを「System.Object」にデシリアライズできませんか?あなたはランタイムのタイプをチェックし、あなたのことをすることができます。 –

答えて

9

私はJson.NETはすべて重いの操作を行います。この方法が好きで、私は先週、同様の何かをしなければならなかったと私は、次のを思い付いた、リストではなく、アレイ

internal class GenericListCreationJsonConverter<T> : JsonConverter 
{ 

    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override bool CanRead 
    { 
     get { return true; } 
    } 

    public override bool CanWrite 
    { 
     get { return false; } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.StartArray) 
     { 
      return serializer.Deserialize<List<T>>(reader); 
     } 
     else 
     { 
      T t = serializer.Deserialize<T>(reader); 
      return new List<T>(new[] { t }); 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
+0

優秀なおかげで、私は最終的に似たようなものを見つけ出すことになりましたが、私はジェネリックスと闘っていたので、あなたの方法が好きです。 – NibblyPig

1

の罰金働きます持ち上げる。その結果、Json.NETがサポートするもの(List <>、ArrayList、厳密な型付けされた配列など)をサポートしています。

public class FlexibleCollectionConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.StartArray) 
     { 
      return serializer.Deserialize(reader, objectType); 
     } 

     var array = new JArray(JToken.ReadFrom(reader)); 
     return array.ToObject(objectType); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof (IEnumerable).IsAssignableFrom(objectType); 
    } 
} 
+0

json配列 –

関連する問題