如何将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[,,]'.
答案 0 :(得分: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
]
]
}");
然后您可以直接使用字典或将其转换为数组。 修改:正如对此评论中所指出的,您还可以考虑将其反序列化为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
]
]
]");
正如你所看到的,我刚刚删除了&#34; 0&#34;和&#34; 1&#34;并用[]替换{}。如果你有能力控制你如何以某种方式接收JSON,那么在我看来这可能是更好的解决方案,因为它匹配你所请求的类型,而不必对其进行任何进一步的操作。
答案 1 :(得分:0)
Json.NET期望多维数组的格式就像JSON文件中的3d锯齿状数组,但是你的数据格式就像是2d锯齿状数组的字典。您可以使用custom JsonConverter
将这种格式的JSON转换为3d数组,如下所示:
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字符串解析为JObject
,则可以使用转换器使用JToken.ToObject<T>(JsonSerializer)
反序列化为所需类型:
var array = jObj.ToObject<double[, ,]>(JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new[] { new Array3DConverter() } }));
为了灵活使用,转换器会测试是否将传入的JSON格式化为对象或数组并做出适当的响应。
注意 - 只进行轻微测试。