将JSON对象反序列化为DataTable报错,如何正确转换?
JSON对象转DataTable报错处理
错误原因
你遇到的报错:
"Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1."
是因为JsonConvert.DeserializeObject<DataTable>()要求传入的JSON是数组格式(用[]包裹),但你的JSON最外层是对象(用{}包裹),直接反序列化自然会失败。你的JSON里真正需要转成DataTable的是Data字段下的数组内容。
解决方法
下面提供两种可行的修改方案,任选其一即可:
方案一:定义实体类解析(类型安全)
先定义对应JSON结构的实体类:
public class RootObject { public string ServiceName { get; set; } public string origin { get; set; } public List<DataItem> Data { get; set; } } public class DataItem { public int status { get; set; } public string statusMessage { get; set; } public string url { get; set; } }
然后修改你的业务代码:
DataTable dsAcknowledgement = new DataTable(); int Count = 1; // 先解析整个JSON对象 var root = JsonConvert.DeserializeObject<RootObject>(Convert.ToString(Input)); // 将Data列表转成DataTable dsAcknowledgement = JsonConvert.DeserializeObject<DataTable>(JsonConvert.SerializeObject(root.Data)); foreach (DataRow dr in dsAcknowledgement.Rows) { string encrypteddata = Convert.ToString(dr["url"]); string DecrypteUrl = SbntAPICrypto.Decrypt(Encrypt_AES256_Key, Encrypt_AES256_iv, encrypteddata); // 把解密后的值写回DataRow,否则修改不会生效 dr["url"] = DecrypteUrl; Count++; } // 将修改后的DataTable放回原对象,再序列化 root.Data = JsonConvert.DeserializeObject<List<DataItem>>(JsonConvert.SerializeObject(dsAcknowledgement)); Input = JsonConvert.SerializeObject(root); return ShipmateWebService(Input);
方案二:用JObject直接提取数组(无需定义类)
如果不想写实体类,可以用JObject直接操作JSON:
DataTable dsAcknowledgement = new DataTable(); int Count = 1; // 解析整个JSON对象 JObject jsonObj = JObject.Parse(Convert.ToString(Input)); // 提取Data字段下的数组 JArray dataArray = (JArray)jsonObj["Data"]; // 转成DataTable dsAcknowledgement = dataArray.ToObject<DataTable>(); foreach (DataRow dr in dsAcknowledgement.Rows) { string encrypteddata = Convert.ToString(dr["url"]); string DecrypteUrl = SbntAPICrypto.Decrypt(Encrypt_AES256_Key, Encrypt_AES256_iv, encrypteddata); dr["url"] = DecrypteUrl; Count++; } // 将修改后的DataTable放回原JSON对象 jsonObj["Data"] = JArray.FromObject(dsAcknowledgement); Input = jsonObj.ToString(); return ShipmateWebService(Input);
注意点
- 原代码中仅解密了
url但未将解密后的值写回DataRow,若需要保留修改结果,必须加上dr["url"] = DecrypteUrl这行代码。 - 如果后续需要把完整JSON传回服务,记得将修改后的DataTable重新放回原JSON结构中,而不是直接序列化DataTable。
内容的提问来源于stack exchange,提问作者keerthana
相关产品推荐
相关产品推荐

