将 JSON 数组反序列化为 List<T> C# 时出错
Posted
技术标签:
【中文标题】将 JSON 数组反序列化为 List<T> C# 时出错【英文标题】:Error Deserializing JSON Array to List<T> C# 【发布时间】:2021-10-11 12:04:13 【问题描述】:我正在尝试反序列化 JSON 数组,我有一个节点接收发布请求并生成 C# 子进程,JSON 数组通过 tmp 文件传入。当我尝试反序列化 JSON 数组时,它会抛出此错误:
Error: Command failed: dotnet OptiTools.dll "/tmp/tmp-1-FtT45M2y3swD"
Unhandled exception. Newtonsoft.Json.JsonSerializationException: Error converting value "[ "lat" : 38.904896, "lng" : -99.340191, "name" : "1" , "lat" : 38.911362, "lng" : -99.354436, "name" : "2" , "lat" : 38.895442, "lng" : -99.318193, "name" : "3" , "lat" : 38.889632, "lng" : -99.318160, "name" : "4" , "lat" : 38.885637, "lng" : -99.320847, "name" : "5" , "lat" : 38.885635, "lng" : -99.321922, "name" : "6" , "lat" : 38.885781, "lng" : -99.333766, "name" : "7" , "lat" : 38.887466, "lng" : -99.339046, "name" : "8" , "lat" : 38.885649, "lng" : -99.336521, "name" : "9" , "lat" : 38.886740, "lng" : -99.352277, "name" : "10" , "lat" : 38.885956, "lng" : -99.324307, "name" : "11" , "lat" : 38.886353, "lng" : -99.323947, "name" : "12" , "lat" : 38.889276, "lng" : -99.319662, "name" : "13" , "lat" : 38.889065, "lng" : -99.319364, "name" : "14" , "lat" : 38.887511, "lng" : -99.319004, "name" : "15" , "lat" : 38.887947, "lng" : -99.320324, "name" : "16" , "lat" : 38.880091, "lng" : -99.317064, "name" : "17" , "lat" : 38.880365, "lng" : -99.317002, "name" : "18" , "lat" : 38.880087, "lng" : -99.315899, "name" : "19" , "lat" : 38.878123, "lng" : -99.314144, "name" : "20" , "lat" : 38.878123, "lng" : -99.315373, "name" : "21" , "lat" : 38.879612, "lng" : -99.315917, "name" : "22" , "lat" : 38.879633, "lng" : -99.317538, "name" : "23" , "lat" : 38.879511, "lng" : -99.318917, "name" : "24" , "lat" : 38.872725, "lng" : -99.317589, "name" : "25" , "lat" : 38.871773, "lng" : -99.316660, "name" : "26" , "lat" : 38.875437, "lng" : -99.317690, "name" : "27" , "lat" : 38.878437, "lng" : -99.317671, "name" : "28" , "lat" : 38.884577, "lng" : -99.317633, "name" : "29" , "lat" : 38.892398, "lng" : -99.321025, "name" : "31" , "lat" : 38.892897, "lng" : -99.324546, "name" : "32" , "lat" : 38.889882, "lng" : -99.333179, "name" : "33" , "lat" : 38.891063, "lng" : -99.333657, "name" : "34" , "lat" : 38.891065, "lng" : -99.333364, "name" : "35" , "lat" : 38.890792, "lng" : -99.333155, "name" : "36" , "lat" : 38.885620, "lng" : -99.334919, "name" : "37" , "lat" : 38.893812, "lng" : -99.336019, "name" : "38" , "lat" : 38.895593, "lng" : -99.332730, "name" : "39" , "lat" : 38.898277, "lng" : -99.335429, "name" : "40" , "lat" : 38.897998, "lng" : -99.331866, "name" : "41" , "lat" : 38.897998, "lng" : -99.333338, "name" : "42" , "lat" : 38.898068, "lng" : -99.332990, "name" : "43" , "lat" : 38.893207, "lng" : -99.328365, "name" : "44" , "lat" : 38.894332, "lng" : -99.333072, "name" : "45" , "lat" : 38.896496, "lng" : -99.331118, "name" : "46" , "lat" : 38.894145, "lng" : -99.327817, "name" : "47" , "lat" : 38.893864, "lng" : -99.327712, "name" : "48" , "lat" : 38.892924, "lng" : -99.327338, "name" : "49" , "lat" : 38.886863, "lng" : -99.327525, "name" : "50" , "lat" : 38.885832, "lng" : -99.325107, "name" : "51" , "lat" : 38.888653, "lng" : -99.326059, "name" : "52" , "lat" : 38.891872, "lng" : -99.324385, "name" : "53" , "lat" : 38.891696, "lng" : -99.323332, "name" : "54" , "lat" : 38.895412, "lng" : -99.320524, "name" : "55" , "lat" : 38.895387, "lng" : -99.323585, "name" : "56" , "lat" : 38.896950, "lng" : -99.326502, "name" : "57" , "lat" : 38.896957, "lng" : -99.323612, "name" : "58" , "lat" : 38.896700, "lng" : -99.320395, "name" : "59" , "lat" : 38.894557, "lng" : -99.320348, "name" : "60" , "lat" : 38.893441, "lng" : -99.323515, "name" : "61" , "lat" : 38.893441, "lng" : -99.323637, "name" : "62" , "lat" : 38.897367, "lng" : -99.327636, "name" : "63" , "lat" : 38.899215, "lng" : -99.327631, "name" : "64" , "lat" : 38.894731, "lng" : -99.331423, "name" : "65" , "lat" : 38.892939, "lng" : -99.330233, "name" : "66" , "lat" : 38.892921, "lng" : -99.330233, "name" : "67" , "lat" : 38.889079, "lng" : -99.330286, "name" : "68" , "lat" : 38.888606, "lng" : -99.330295, "name" : "69" , "lat" : 38.888508, "lng" : -99.331809, "name" : "70" , "lat" : 38.888655, "lng" : -99.329502, "name" : "71" , "lat" : 38.886589, "lng" : -99.317605, "name" : "72" , "lat" : 38.886589, "lng" : -99.317605, "name" : "73" , "lat" : 38.887620, "lng" : -99.317617, "name" : "74" , "lat" : 38.894740, "lng" : -99.317583, "name" : "75" , "lat" : 38.895597, "lng" : -99.317589, "name" : "76" , "lat" : 38.903833, "lng" : -99.317629, "name" : "77" , "lat" : 38.903859, "lng" : -99.317628, "name" : "78" , "lat" : 38.907180, "lng" : -99.319754, "name" : "79" , "lat" : 38.902268, "lng" : -99.317992, "name" : "80" , "lat" : 38.901969, "lng" : -99.317995, "name" : "82" , "lat" : 38.901969, "lng" : -99.317995, "name" : "83" , "lat" : 38.901969, "lng" : -99.317995, "name" : "84" , "lat" : 38.900166, "lng" : -99.306594, "name" : "86" , "lat" : 38.899893, "lng" : -99.313189, "name" : "87" , "lat" : 38.899877, "lng" : -99.315322, "name" : "88" , "lat" : 38.907873, "lng" : -99.315153, "name" : "89" , "lat" : 38.901351, "lng" : -99.321161, "name" : "90" , "lat" : 38.889548, "lng" : -99.317579, "name" : "91" ] " to type 'System.Collections.Generic.List`1[OptiTools.Locations]'. Path '', line 1, position 5805.
---> System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[OptiTools.Locations].
at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
--- End of inner exception stack trace ---
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
at OptiTools.JsonConverter.ExtractLoc(String jsonIn) in C:\Users\ryanb\Documents\Projects\Reoptimization\OptiTools\OptiTools\OptiTools\JsonConverter.cs:line 14
at OptiTools.Program.Main(String[] args) in C:\Users\ryanb\Documents\Projects\Reoptimization\OptiTools\OptiTools\OptiTools\Program.cs:line 14
Aborted
at ChildProcess.exithandler (child_process.js:275:12)
at emitTwo (events.js:126:13)
at ChildProcess.emit (events.js:214:7)
at maybeClose (internal/child_process.js:925:16)
at Socket.stream.socket.on (internal/child_process.js:346:11)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at Pipe._handle.close [as _onclose] (net.js:567:12)
在我看来,JSON 数组的格式正确,可以反序列化为此位置列表,但由于某种原因无法转换。 Locations 对象很简单,应该不是问题
using System;
using System.Collections.Generic;
using System.Text;
namespace OptiTools
public class Locations
public double lat get; set;
public double lng get; set;
public string name get; set;
这也是我为转换 JSON 所做的类的代码:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text;
using Newtonsoft.Json.Linq;
namespace OptiTools
public static class JsonConverter
public static List<Locations> ExtractLoc(string jsonIn)
List<Locations> locs = JsonConvert.DeserializeObject<List<Locations>>(jsonIn);
return locs;
编辑:nodeJS 代码:
// javascript source code
//const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const tmp = require('tmp');
const fs = require('fs');
const app = express();
const router = express.Router();
const hostname = '0.0.0.0';
const port = 3000;
const cpro = require('child_process');
const file = 'OptiTools.dll';
var outp = "";
app.use(cors());
app.use(bodyParser.urlencoded( extended: false ));
app.use(bodyParser.json());
app.post('/', (req, res) =>
console.log(JSON.stringify(req.body.data));
tmp.file(function createTmp(err, path, fd, cleanupCallback)
if (err) throw err;
fs.writeFile(path, [JSON.stringify(req.body.data)], (err) =>
if (err) throw err else
console.log(path)
var runner = cpro.exec(`dotnet $file "$path"`, cwd: "../OptiTools/OptiTools/bin/Release/netcoreapp3.1" , (error, out, err) =>
if (error)
throw error;
else
outp = out;
res.statusCode = 200;
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'application/json');
res.send(outp);
cleanupCallback();
);
);
);
);
app.listen(port, hostname, () =>
console.log(`Server running at http://$hostname:$port/`);
);
节点将此记录为 JSON:
"[ \"lat\" : 38.904896, \"lng\" : -99.340191, \"name\" : \"1\" , \"lat\" : 38.911362, \"lng\" : -99.354436, \"name\" : \"2\" , \"lat\" : 38.895442, \"lng\" : -99.318193, \"name\" : \"3\" , \"lat\" : 38.889632, \"lng\" : -99.318160, \"name\" : \"4\" , \"lat\" : 38.885637, \"lng\" : -99.320847, \"name\" : \"5\" , \"lat\" : 38.885635, \"lng\" : -99.321922, \"name\" : \"6\" , \"lat\" : 38.885781, \"lng\" : -99.333766, \"name\" : \"7\" , \"lat\" : 38.887466, \"lng\" : -99.339046, \"name\" : \"8\" , \"lat\" : 38.885649, \"lng\" : -99.336521, \"name\" : \"9\" , \"lat\" : 38.886740, \"lng\" : -99.352277, \"name\" : \"10\" , \"lat\" : 38.885956, \"lng\" : -99.324307, \"name\" : \"11\" , \"lat\" : 38.886353, \"lng\" : -99.323947, \"name\" : \"12\" , \"lat\" : 38.889276, \"lng\" : -99.319662, \"name\" : \"13\" , \"lat\" : 38.889065, \"lng\" : -99.319364, \"name\" : \"14\" , \"lat\" : 38.887511, \"lng\" : -99.319004, \"name\" : \"15\" , \"lat\" : 38.887947, \"lng\" : -99.320324, \"name\" : \"16\" , \"lat\" : 38.880091, \"lng\" : -99.317064, \"name\" : \"17\" , \"lat\" : 38.880365, \"lng\" : -99.317002, \"name\" : \"18\" , \"lat\" : 38.880087, \"lng\" : -99.315899, \"name\" : \"19\" , \"lat\" : 38.878123, \"lng\" : -99.314144, \"name\" : \"20\" , \"lat\" : 38.878123, \"lng\" : -99.315373, \"name\" : \"21\" , \"lat\" : 38.879612, \"lng\" : -99.315917, \"name\" : \"22\" , \"lat\" : 38.879633, \"lng\" : -99.317538, \"name\" : \"23\" , \"lat\" : 38.879511, \"lng\" : -99.318917, \"name\" : \"24\" , \"lat\" : 38.872725, \"lng\" : -99.317589, \"name\" : \"25\" ] "
【问题讨论】:
您在此处拥有的 JSON(偷偷地嵌入在错误消息中而不是在问题中发布)可以完美地转换为您在此处显示的类。还有一些你没有向我们展示的东西。 这是为了让问题变得有意义。最好将代码(和 JSON)减少到最低限度。您是否需要 5000 个字符的 JSON 来证明它不起作用?只需创建一个minimal reproducible example 我的猜测是您的 JSON 字符串是错误的并且是双重编码的。检查原始字符串,它是否被"...."
包围?但是,如果您不向我们展示 ACTUAL JSON,那么我们将无能为力。
错误Could not cast or convert from System.String to System.Collections.Generic.List``1[OptiTools.Locations]
表明DavidG是对的。
看起来你在调用 JSON.stringify
的字符串已经是 JSON。
【参考方案1】:
您在 NodeJS 应用程序中对 JSON 进行双重编码。这意味着在 C# 代码中,JSON 是一个简单的字符串,因此理论上您可以在那里对其进行两次解码:
var decodedJson = JsonConvert.DeserializeObject<string>(jsonIn);
List<Locations> locs = JsonConvert.DeserializeObject<List<Locations>>(decodedJson);
当然,那将是相当愚蠢和浪费资源的。相反,您应该修复 NodeJS 应用程序,使其不会通过删除 JSON.stringify
来进行双重编码。
【讨论】:
以上是关于将 JSON 数组反序列化为 List<T> C# 时出错的主要内容,如果未能解决你的问题,请参考以下文章
将 JSON 反序列化为 List<List<KeyValuePair>> 结果为空
将 JSON 对象反序列化为 List<type> 不适用于 asmx 服务