2016-09-19 19 views
0

JObjectを3D配列に変換するにはどうすればよいですか?JObjectを多次元配列に変換する

{ 
    "0": [ 
    [ 
     1.0, 
     2.0, 
     3.0 
    ], 
    [ 
     4.0, 
     5.0, 
     6.0 
    ] 
    ], 
    "1": [ 
    [ 
     7.0, 
     8.0, 
     9.0 
    ], 
    [ 
     10.0, 
     11.0, 
     12.0 
    ] 
    ] 
} 

私はdouble[,,]にキャストしようとしましたが、それは私のために

Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'System.Double[,,]'. 

答えて

1

次作品というエラーで失敗します:

var deserailizationExp = JsonConvert.DeserializeObject<Dictionary<string, double[,]>>(@" 
      {""0"": [ 
      [ 
       1.0, 
       2.0, 
       3.0 
      ], 
      [ 
       4.0, 
       5.0, 
       6.0 
      ] 
      ], 
      ""1"": [ 
      [ 
       7.0, 
       8.0, 
       9.0 
      ], 
      [ 
       10.0, 
       11.0, 
       12.0 
      ] 
      ] 
     }"); 
を、私は、次のようなフォーマットされJOBJECTを持っています

辞書を直接使用することも、配列に変換することもできます。 編集:これについてのコメントで指摘したように、これをタイプSortedDictionary<int, double[,]>に逆シリアル化することも考えられます。私はタイプとしてそれが私のために働いたことをテストしました。

また、あなたは次の操作を行うことができますJSON変更した場合:

var otherDes = JsonConvert.DeserializeObject<double[,,]>(@" 
      [[ 
      [ 
       1.0, 
       2.0, 
       3.0 
      ], 
      [ 
       4.0, 
       5.0, 
       6.0 
      ] 
      ], 
      [ 
      [ 
       7.0, 
       8.0, 
       9.0 
      ], 
      [ 
       10.0, 
       11.0, 
       12.0 
      ] 
      ] 
     ]"); 

あなたが見ることができるように、私は "0" と "1" を取り出し、[]と{}置き換えを。 JSONをどうやって受け取っているかを制御する能力があれば、それはそれ以上の操作をすることなく、要求されたタイプと一致するので、おそらく私の意見ではより良い解決策になるでしょう。

+0

プロパティ名が明確なインデックスであるため、 'Dictionary 'も動作するはずです。 'Dictionary'が順序付けされていないことに注意してください。そうすれば、逆シリアル化中にエントリの順序が乱れることがあります。 'SortedDictionary 'は良いでしょう。 – dbc

+0

ウェブサービスからコンテンツを受け取っている場合は動作しません –

0

Json.NETは、多次元配列をJSONファイルの3Dギザギザの配列のようにフォーマットすることを期待していますが、あなたのものは2dのギザギザの配列の辞書のように書式設定されています。あなたはそうのように、3D配列に、このような形式のJSONを変換するcustom JsonConverterを使用することができます。

public class Array3DConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     if (!objectType.IsArray) 
      return false; 
     return objectType.GetArrayRank() == 3; 
    } 

    object ReadJsonGeneric<T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     if (reader.TokenType == JsonToken.StartArray) 
     { 
      // Handle case when it's actually a 3d array in the JSON. 
      var list = serializer.Deserialize<List<List<List<T>>>>(reader); 
      return list.Select((l, i) => new KeyValuePair<int, List<List<T>>>(i, l)).To3DArray(); 
     } 
     else if (reader.TokenType == JsonToken.StartObject) 
     { 
      // Handle case when it's a dictionary of key/value pairs. 
      var dictionary = serializer.Deserialize<SortedDictionary<int, List<List<T>>>>(reader); 
      return dictionary.To3DArray(); 
     } 
     else 
     { 
      throw new JsonSerializationException("Invalid reader.TokenType " + reader.TokenType); 
     } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     try 
     { 
      var elementType = objectType.GetElementType(); 
      var method = GetType().GetMethod("ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 
      return method.MakeGenericMethod(new[] { elementType }).Invoke(this, new object[] { reader, objectType, existingValue, serializer }); 
     } 
     catch (TargetInvocationException ex) 
     { 
      // Wrap the TargetInvocationException in a JsonSerializerException 
      throw new JsonSerializationException("Failed to deserialize " + objectType, ex); 
     } 
    } 

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

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

public static class EnumerableExtensions 
{ 
    public static T[,,] To3DArray<T>(this IEnumerable<KeyValuePair<int, List<List<T>>>> jaggedArray) 
    { 
     if (jaggedArray == null) 
      throw new ArgumentNullException("jaggedArray"); 
     var counts = new int[3]; 
     foreach (var pair in jaggedArray) 
     { 
      var i = pair.Key; 
      counts[0] = Math.Max(i + 1, counts[0]); 
      if (pair.Value == null) 
       continue; 
      var jCount = pair.Value.Count; 
      counts[1] = Math.Max(jCount, counts[1]); 
      for (int j = 0; j < jCount; j++) 
      { 
       if (pair.Value[j] == null) 
        continue; 
       var kCount = pair.Value[j].Count; 
       counts[2] = Math.Max(kCount, counts[2]); 
      } 
     } 
     var array = new T[counts[0], counts[1], counts[2]]; 
     foreach (var pair in jaggedArray) 
     { 
      var i = pair.Key; 
      if (pair.Value == null) 
       continue; 
      var jCount = pair.Value.Count; 
      for (int j = 0; j < jCount; j++) 
      { 
       if (pair.Value[j] == null) 
        continue; 
       var kCount = pair.Value[j].Count; 
       for (int k = 0; k < kCount; k++) 
        array[i, j, k] = pair.Value[j][k]; 
      } 
     } 
     return array; 
    } 
} 

そして、それが好きで使用します。

var array = JsonConvert.DeserializeObject<double[, ,]>(jsonString, new JsonSerializerSettings { Converters = new[] { new Array3DConverter() } }); 

それとも、あなたはすでににあなたのJSON文字列を解析されている場合

var array = jObj.ToObject<double[, ,]>(JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new[] { new Array3DConverter() } })); 

使用中の柔軟性を高めるため、コンバータのテストへ:JObjectは、あなたのコンバータを使用して、ご希望のタイプにデシリアライズするJToken.ToObject<T>(JsonSerializer)を使用することができます受信JSONがオブジェクトまたは配列としてフォーマットされ、適切に応答するかどうかを確認してください。

注 - 軽度にテストされています。

関連する問題