2012-07-19 13 views
14

私はNewtonsoft JSON.NETを使用するためにいくつかの古い作業を変換しようとしています。 System.Web.Script.Serialization.JavaScriptSerializer.Deserializeメソッドを使用するデフォルトの処理(たとえば、ターゲットタイプが指定されていない場合)は、内部オブジェクトに対してDictionary<string,object>を返します。JSictionaryをIDictionary <string、object>に再帰的に逆シリアル化します。

これは実際にはExpandoObjectsで使用される基になるタイプであるため、JSONの実際には本当に便利な基本タイプであり、動的タイプにとって最も賢明な内部実装です。

私は例えば、このタイプを指定した場合:

var dict = JsonConvert.DeserializeObject<Dictionary<string,object>>(json); 

をJSON.NETは正しく、最も外側のオブジェクト構造をデシリアライズしますが、それは任意の内部構造についてJObjectタイプを返します。私が本当に必要とするのは、内側のオブジェクト型構造に同じ外部構造を使用することです。

返される最も外側の型だけでなく、内部オブジェクトに使用する型を指定する方法はありますか?

答えて

7

Jsonを使用して複雑なオブジェクトをデシリアライズするときは、JsonSerializerの設定をパラメータとして追加する必要があります。これにより、すべての内部型が正しくデシリアライズされるようになります。あなたのオブジェクトをシリアル化するとき

private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings 
    { 
     TypeNameHandling = TypeNameHandling.All, 
     TypeNameAssemblyFormat = FormatterAssemblyStyle.Full 
    }; 

、あなたはSerializerSettingsを使用することができます。

string json= JsonConvert.SerializeObject(myObject, _jsonSettings) 

を次にあなたがデシリアライズされ、使用を:あなたはシリアライズするときも

var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, _jsonSettings); 

は、にJsonSerializerSettingsを追加しますあなたのSerializeObject(オブジェクト、設定)

編集:あなたはまた、彼は必要な場合はTypeNameHandlingとTypeNameAssemblyFormatを使用します。私はそれらをそれぞれ 'All'と 'Full'に設定して、複雑なオブジェクトが正しくシリアル化され、デシリアライズされるようにしましたが、intellisenseは他の選択肢を提供します。

+0

これは正解ですか? –

+1

@ LukePuplett質問に基づいて、これが正しいとは思わない。 –

+0

質問に基づいて、これは正しい答えではありません。 –

15

json.Netにjson文字列を逆シリアル化するにはネストされたオブジェクトと配列をデシリアライズすることを含むIDictionary<string, object>に入れると、Json.Netが提供する抽象クラスJsonConverterから派生したカスタムクラスを作成する必要があります。

派生したのはJsonConverterです.jsonとの間でオブジェクトの書き込み方法を実装しています。

あなたはこのようなあなたのカスタムJsonConverterを使用することができます。

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

    private void WriteValue(JsonWriter writer, object value) { 
     var t = JToken.FromObject(value); 
     switch (t.Type) { 
      case JTokenType.Object: 
       this.WriteObject(writer, value); 
       break; 
      case JTokenType.Array: 
       this.WriteArray(writer, value); 
       break; 
      default: 
       writer.WriteValue(value); 
       break; 
     } 
    } 

    private void WriteObject(JsonWriter writer, object value) { 
     writer.WriteStartObject(); 
     var obj = value as IDictionary<string, object>; 
     foreach (var kvp in obj) { 
      writer.WritePropertyName(kvp.Key); 
      this.WriteValue(writer, kvp.Value); 
     } 
     writer.WriteEndObject(); 
    } 

    private void WriteArray(JsonWriter writer, object value) { 
     writer.WriteStartArray(); 
     var array = value as IEnumerable<object>; 
     foreach (var o in array) { 
      this.WriteValue(writer, o); 
     } 
     writer.WriteEndArray(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     return ReadValue(reader); 
    } 

    private object ReadValue(JsonReader reader) { 
     while (reader.TokenType == JsonToken.Comment) { 
      if (!reader.Read()) throw new JsonSerializationException("Unexpected Token when converting IDictionary<string, object>"); 
     } 

     switch (reader.TokenType) { 
      case JsonToken.StartObject: 
       return ReadObject(reader); 
      case JsonToken.StartArray: 
       return this.ReadArray(reader); 
      case JsonToken.Integer: 
      case JsonToken.Float: 
      case JsonToken.String: 
      case JsonToken.Boolean: 
      case JsonToken.Undefined: 
      case JsonToken.Null: 
      case JsonToken.Date: 
      case JsonToken.Bytes: 
       return reader.Value; 
      default: 
       throw new JsonSerializationException 
        (string.Format("Unexpected token when converting IDictionary<string, object>: {0}", reader.TokenType)); 
     } 
    } 

    private object ReadArray(JsonReader reader) { 
     IList<object> list = new List<object>(); 

     while (reader.Read()) { 
      switch (reader.TokenType) { 
       case JsonToken.Comment: 
        break; 
       default: 
        var v = ReadValue(reader); 

        list.Add(v); 
        break; 
       case JsonToken.EndArray: 
        return list; 
      } 
     } 

     throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
    } 

    private object ReadObject(JsonReader reader) { 
     var obj = new Dictionary<string, object>(); 

     while (reader.Read()) { 
      switch (reader.TokenType) { 
       case JsonToken.PropertyName: 
        var propertyName = reader.Value.ToString(); 

        if (!reader.Read()) { 
         throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
        } 

        var v = ReadValue(reader); 

        obj[propertyName] = v; 
        break; 
       case JsonToken.Comment: 
        break; 
       case JsonToken.EndObject: 
        return obj; 
      } 
     } 

     throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
    } 

    public override bool CanConvert(Type objectType) { return typeof(IDictionary<string, object>).IsAssignableFrom(objectType); } 
} 
:ここ

var o = JsonConvert.DeserializeObject<IDictionary<string, object>>(json, new DictionaryConverter()); 

は、私はあなたがあなたの質問にアウトラインとして同じ目標を達成するために、過去に成功を収めて使用したカスタムJsonConverterです

+0

このソリューションは素晴らしいです。ありがとう! – smdrager

+0

[これは他の記事のこの解決策です](http://stackoverflow.com/a/38029052/1062224) –

関連する問題