2016-07-26 3 views
2

私はDictionary<string,object>にデシリアライズする単一レベルのjsonを持っています。Json.Netを使用してください。JSON.netは、宛先がオブジェクトの場合、json配列をJArrayにシリアル化します。どうすれば変更できますか?

ディクショナリの値は、プリミティブ、文字列、または(プリミティブ\文字列)配列です。

プリシリアライズはプリミティブと文字列の処理方法を認識しますが、プリミティブの配列に到達するとプリミティブ配列の代わりにJArrayにデシリアライズされます。

string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}"; 
Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonStr); 

dict["obj"].GetType(); // long 
dict["arr"].GetType(); // JArray. I would like this to be string[]. 

私は、逆シリアル化プロセスに干渉し、代わりにJArrayで立ち往生のプリミティブ配列を作成することができる方法を探しています:

は、ここで私が何を意味するかの小さなコード例を示します。

私はJsonSerializerSettingsでそれを試みましたが、その場を釘付けできませんでした。

+1

参照[どのように私は、ネストされた/再帰的な辞書とリストの中にデシリアライズするJSON.NETを使用しますか?](http://stackoverflow.com/q/5546142/10263) –

答えて

0

なぜなら、JsonConvertにDictionary<string, object>に変換するように指示しているからです。それは、具体的にはObjectに変換されていないという事実に基づいて行われます。その "推測"はJArrayを選んだ、あなたは辞書の値のために複数のタイプを持つことができれば、最高のものは、動的オブジェクトに変換することです。これは、 "arr"の値が配列の場合は配列を返し、値が単純な文字列の場合は文字列を返します。ここで

string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}"; 
     dynamic dict = JsonConvert.DeserializeObject(jsonStr); 
     var arr = dict.arr; 
     string firstelement = arr[0]; // print "1" 
+0

私はそれがない理由を理解しますそれを私が望むように変換してください。私はどうにかして(何らかの理由でConverter経由で)干渉するようにしようとしています。ダイナミックはまだJArrayとして保持されるのでオプションではありません。とにかくありがとう! –

+0

DynamicはそれをJArrayとして保持せず、配列に変換します。 –

+0

はい、あります。私はちょうどそれが100%確実であることを確認した。この行のコードはtrueを返します: 'dict [" arr "] GetType()== typeof(JArray)' –

1

は、これを行うためのハック方法です。私は、2つの一般的な引数:T1とT2を受け付けるカスタムJsonConverterクラスを作成します。 T1は配列の型(この場合は文字列)を示し、T2は他のオブジェクトの型(この場合はlong)を示します。私は基本的に辞書がほしいと思っていますが、その部分を確実に改善することができます。

using System; 
using System.Collections.Generic; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}"; 
      Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonStr, new SpecialConverter<string, long>()); 

      dict["obj"].GetType(); // long 
      dict["arr"].GetType(); // string[]. 
     } 

     class SpecialConverter<T1, T2> : JsonConverter 
     { 
      public override bool CanConvert(Type objectType) 
      { 
       return true; 
      } 

      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
      { 
       JToken token = JToken.Load(reader); 
       var result = new Dictionary<string, object>(); 
       if (result.GetType() == objectType) 
       { 
        foreach (var item in token) 
        { 
         var prop = (JProperty)item; 
         if (prop.Value.Type == JTokenType.Array) 
         { 
          result.Add(prop.Name, prop.Value.ToObject<T1[]>()); 
         } 
         else 
         { 
          result.Add(prop.Name, prop.Value.ToObject<T2>()); 
         } 
        } 

        return result; 
       } 
       else 
       { 
        return null; 
       } 
      } 

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

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

私のオブジェクトは大きく、複雑です。あなたの解決策は実際にシリアライザを書き直すことです。 +1の努力のために、私はもう少し一般的なものを探していて、jsonシリアライザを書き直さないようにしました。 –

+0

@AmirPopovich http://json2csharp.com/のようなものでJSONオブジェクトのクラスを作成しない限り、あなたは 'object []'よりもはるかに優れているとは思えません。 – Ringil

関連する問題