JSON反序列化为DataTable遇格式错误,求排查JSON字符串问题
问题详情
尝试将JSON字符串反序列化为DataTable时触发格式错误,相关代码、JSON字符串及报错信息如下:
C#代码
string str = "{\"Arg1\":\"Arg1Value\",\"Arg2\":\"Arg2Value\",\"DataArray\":[{\"Id\": \"2222\",\"VehicleNo\": \"234354\",\"Amount\":\"1000\"},{\"Id\":\"2226\",\"VehicleNo\":\"2343\",\"Amount\":\"2000\"}]}"; DataTable data = Newtonsoft.Json.JsonConvert.DeserializeObject<DataTable>(str);
原始报错信息
Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1."Data":null,"InnerException":null,"HelpURL":null,"StackTraceString":" at Newtonsoft.Json.Converters.DataTableConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)\r\n at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
报错信息翻译
读取DataTable时遇到意外的JSON令牌。期望数组起始符
[,却得到对象起始符{。路径'',第1行,第1位。"Data":null,"InnerException":null,"HelpURL":null,"StackTraceString":" 在Newtonsoft.Json.Converters.DataTableConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)\r\n 在Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)\r\n 在Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)\r\n 在Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
问题根源
Newtonsoft.Json的DataTableConverter要求反序列化为DataTable的JSON必须以数组([])作为根节点,但你提供的JSON根节点是包含Arg1、Arg2、DataArray三个属性的对象({}),不符合DataTable的反序列化规则。实际对应DataTable数据的是对象内部的DataArray数组。
解决办法
方法1:提取DataArray部分反序列化
先将整个JSON反序列化为临时对象,提取DataArray后再转为DataTable:
var tempObj = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(str, new { DataArray = default(List<object>) }); DataTable data = Newtonsoft.Json.JsonConvert.DeserializeObject<DataTable>(Newtonsoft.Json.JsonConvert.SerializeObject(tempObj.DataArray));
方法2:修改JSON结构(若允许调整输入)
直接将JSON根节点替换为DataArray的数组内容,去掉外层对象:
[{"Id": "2222","VehicleNo": "234354","Amount":"1000"},{"Id":"2226","VehicleNo":"2343","Amount":"2000"}]
之后直接执行反序列化:
string str = "[{\"Id\": \"2222\",\"VehicleNo\": \"234354\",\"Amount\":\"1000\"},{\"Id\":\"2226\",\"VehicleNo\":\"2343\",\"Amount\":\"2000\"}]"; DataTable data = Newtonsoft.Json.JsonConvert.DeserializeObject<DataTable>(str);
方法3:自定义类映射转换
定义匹配JSON结构的类,先反序列化为类实例,再将DataArray转换为DataTable:
public class RootModel { public string Arg1 { get; set; } public string Arg2 { get; set; } public List<DataItem> DataArray { get; set; } } public class DataItem { public string Id { get; set; } public string VehicleNo { get; set; } public string Amount { get; set; } } // 反序列化代码 var root = Newtonsoft.Json.JsonConvert.DeserializeObject<RootModel>(str); DataTable data = Newtonsoft.Json.JsonConvert.DeserializeObject<DataTable>(Newtonsoft.Json.JsonConvert.SerializeObject(root.DataArray));
内容的提问来源于stack exchange,提问作者AMDI

