人们并不总是知道要反序列化的类型。因此,能够获取任何 JSON(包含一些数组)并从中动态生成一个表会很方便。
然而,可能会出现一个问题,即反序列化器不知道在哪里查找要制表的数组。发生这种情况时,我们会收到类似于以下内容的错误消息:
读取 DataTable 时出现意外的 JSON 令牌。预期 StartArray,得到 StartObject。路径'',第 1 行,位置 1。
即使我们给予鼓励或相应地准备我们的 json,数组中的“对象”类型仍然可以防止制表的发生,其中反序列化器不知道如何用行等表示对象。在这种情况下,出现类似以下的错误:
读取 DataTable 时出现意外的 JSON 令牌:StartObject。路径 '[0].__metadata',第 3 行,位置 19。
下面的示例 JSON 包含这两个有问题的功能:
{
"results":
[
{
"Enabled": true,
"Id": 106,
"Name": "item 1",
},
{
"Enabled": false,
"Id": 107,
"Name": "item 2",
"__metadata": { "Id": 4013 }
}
]
}
那么我们如何解决这个问题,并且仍然保持不知道要反序列化的类型的灵活性呢?
好吧,这是我想出的一个简单方法(假设您很乐意忽略对象类型的属性,例如上面示例中的 __metadata):
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Linq;
...
public static DataTable Tabulate(string json)
{
var jsonLinq = JObject.Parse(json);
// Find the first array using Linq
var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
var trgArray = new JArray();
foreach (JObject row in srcArray.Children<JObject>())
{
var cleanRow = new JObject();
foreach (JProperty column in row.Properties())
{
// Only include JValue types
if (column.Value is JValue)
{
cleanRow.Add(column.Name, column.Value);
}
}
trgArray.Add(cleanRow);
}
return JsonConvert.DeserializeObject<DataTable>(trgArray.ToString());
}
我知道这可能更“LINQy”,并且异常处理绝对为零,但希望能传达这个概念。
我们开始在我的工作中使用越来越多的服务来返回 JSON,因此将自己从强类型化中解放出来是我的明显偏好,因为我很懒!