嵌套JSON转C# Model反序列化失败问题求助
解决JSON反序列化为C# Model的错误问题
错误信息
无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Collections.Generic.List`1[convert_json_to_model.Fields]',因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。
要修复此错误,请将JSON修改为JSON数组,或者修改反序列化类型为可从JSON对象反序列化的常规.NET类型(例如不是整数等基元类型,也不是数组或List等集合类型)。也可以为类型添加JsonObjectAttribute以强制其从JSON对象反序列化。
路径'nhits',第1行,位置9。
部分JSON数据
{"nhits":17933,"parameters":{"dataset":["osm-fr-bars@babel"],"rows":3,"start":0,"format":"json","timezone":"UTC"},"records":[{"datasetid":"osm-fr-bars@babel","recordid":"d95394fd7d34aa34aa9b236661bce9cda534a8ab","fields":{"other_tags":"{\"cuisine\": \"tapas\", \"ref:FR:CRTA\": \"RESAQU047V506W6V\", \"capacity\": \"14\", \"description\": \"Tous les jours \u00e0 partir de 7h\", \"source\": \"BDOrtho IGN; Cadastre M\u00e0J 2015; Sirtaqui\", \"outdoor_seating\": \"yes\", \"source:ref:FR:CRTA\": \"Sirtaqui\"}","name":"Au boin coin","geo_point_2d":[44.0549704,0.2603921],"phone":"+33 5 53 65 67 45"},"geometry":{"type":"Point","coordinates":[0.2603921,44.0549704]}}]}
生成的C#模型代码
public class Fields { [JsonProperty("other_tags")] public string OtherTags { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("geo_point_2d")] public List<double> GeoPoint2d { get; set; } [JsonProperty("phone")] public string Phone { get; set; } } public class Geometry { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("coordinates")] public List<double> Coordinates { get; set; } } public class Record { [JsonProperty("datasetid")] public string Datasetid { get; set; } [JsonProperty("recordid")] public string Recordid { get; set; } [JsonProperty("fields")] public Fields Fields { get; set; } [JsonProperty("geometry")] public Geometry Geometry { get; set; } } public class Root { [JsonProperty("records")] public List<Record> Records { get; set; } }
出错的反序列化代码
static async Task Main(string[] args) { string url = "https://data.opendatasoft.com/api/records/1.0/search/?dataset=osm-fr-bars%40babel&rows=30"; HttpClient httpClient = new HttpClient(); try { var httpResponseMessage = await httpClient.GetAsync(url); string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync(); List<Fields> myBars = JsonConvert.DeserializeObject<List<Fields>>(jsonResponse); foreach (var bar in myBars) { Console.WriteLine($"{bar.Name}"); } } catch(Exception ex) { Console.WriteLine(ex.Message); } }
解决方案
问题核心是:你试图把整个JSON对象直接反序列化为List<Fields>类型,但实际返回的JSON根节点是一个包含nhits、parameters、records的顶层对象,Fields集合嵌套在records数组的每一项里。
修改反序列化逻辑,先将JSON反序列化为Root类型,再从Root.Records中提取Fields:
static async Task Main(string[] args) { string url = "https://data.opendatasoft.com/api/records/1.0/search/?dataset=osm-fr-bars%40babel&rows=30"; HttpClient httpClient = new HttpClient(); try { var httpResponseMessage = await httpClient.GetAsync(url); string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync(); // 先反序列化为Root类型 Root root = JsonConvert.DeserializeObject<Root>(jsonResponse); // 提取所有Records中的Fields List<Fields> myBars = root.Records.Select(r => r.Fields).ToList(); foreach (var bar in myBars) { Console.WriteLine($"{bar.Name}"); } } catch(Exception ex) { Console.WriteLine(ex.Message); } }
额外说明:如果需要使用nhits或parameters的数据,可以给Root类补充对应的属性:
public class Root { [JsonProperty("nhits")] public int Nhits { get; set; } [JsonProperty("parameters")] public Parameters Parameters { get; set; } [JsonProperty("records")] public List<Record> Records { get; set; } } public class Parameters { [JsonProperty("dataset")] public List<string> Dataset { get; set; } [JsonProperty("rows")] public int Rows { get; set; } [JsonProperty("start")] public int Start { get; set; } [JsonProperty("format")] public string Format { get; set; } [JsonProperty("timezone")] public string Timezone { get; set; } }
内容的提问来源于stack exchange,提问作者saad moujid
相关产品推荐
相关产品推荐

