JArray 内容类型的运行时确定

Runtime determination of JArray content types

我必须在运行时确定要在相应方法中使用的 JSON 的 JArray 对象的类型:

我的部分 JSON 看起来像:

{
  "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib",
  "listdouble": {
    "$type": "System.Collections.Generic.List`1[[System.Double, mscorlib]], mscorlib",
    "$values": [
      1,
      3
    ]
  },
  "listbool": {
    "$type": "System.Collections.Generic.List`1[[System.Boolean, mscorlib]], mscorlib",
    "$values": [
      true,
      false
    ]
  },
  "liststring": {
    "$type": "System.Collections.Generic.List`1[[System.String, mscorlib]], mscorlib",
    "$values": [
      null,
      " ",
      "New String"
    ]
  }
}

这是从 Dictionay<string, object> 连载的 Json 的一部分。在运行时,它被反序列化为一个字典,键映射到 JArrays。一旦我知道其中包含的数据类型,我就可以在 JArray 上使用 ToObject 方法,但是如何确定它是由什么类型组成的呢?比如字典键是映射到 List<double> 还是 List<bool> ?

我会做的是使用动态对象反序列化 JSON like

dynamic d = JsonConvert.DeserializeObject(jsonString);

然后通过

访问数组
JArray arrayOfDoubles = d.listdouble.values;

并检查包含的类型

List<JTokenType> listOfTypes = arrayOfDoubles.GroupBy(item => item.Type).Select(item => item.Key).ToList();

在这种情况下,listOfTypes 的输出是

[0] Integer

但你当然可以从中得到一个双精度数组。

List<double> listOfDoubles = arrayOfDoubles.ToObject<List<double>>();

结果就好了:

[0] 1.0
[1] 3.0

与您的布尔列表相同:

JArray arrayOfBools = d.listbool.values;
listOfTypes = arrayOfBools.GroupBy(item => item.Type).Select(item => item.Key).ToList();

listOfTypes 的输出

[0] Boolean

反序列化:

List<bool> listOfBools = a.ToObject<List<bool>>();

输出:

[0] true
[1] true

同样适用于字符串。

您还可以通过

从您提供的类型反序列化您的数组
var type = d.listdouble.type; // "System.Collections.Generic.List`1[[System.Double, mscorlib]], mscorlib"

var myType = Type.GetType(type.ToString()); // get the type out of it
var myGenericList = arrayOfDoubles.ToObject(myType);

myGenericList 的类型为 {System.Collections.Generic.List<double>},值为 [1.0, 3.0]。工作正常。

因此您可以根据 json 数组中的元素检查 json 类型 d.listdouble.type 以确保它会被反序列化。

希望对您有所帮助!