使用 Newtonsoft 反序列化未命名数组的 JSON 数组
Posted
技术标签:
【中文标题】使用 Newtonsoft 反序列化未命名数组的 JSON 数组【英文标题】:Deserialize JSON array of unnamed arrays using Newtonsoft 【发布时间】:2020-02-29 14:54:04 【问题描述】:我正在尝试反序列化一个 JSON 对象,该对象具有一组未命名的数组并且遇到了一些问题。我正在运行测试的代码:
var json = " \"Triangles\": [[1337],[1338],[1339]]";
var mesh = JsonConvert.DeserializeObject<Mesh>(json);
以及感兴趣的类别:
public class Mesh
[JsonProperty]
public Triangle[] Triangles get; set;
public class Triangle
[JsonProperty]
public int[] Indices get; set;
运行代码并尝试使用 Newtonsoft 反序列化我得到以下异常:
Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ConsoleApp1.Triangle' because the type requires a JSON object (e.g. "name":"value") to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. "name":"value") or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'triangles[0]', line 1, position 17.
将 [JsonArray] 添加到 Triangle 类会导致以下异常:
Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Cannot create and populate list type ConsoleApp1.Triangle. Path 'Triangles[0]', line 1, position 17.
我错过了什么?
编辑:我显然忘记提及的一件重要事情是,出于语义原因,我想将其反序列化为帖子中列出的类。也就是说,虽然将 Triangles 反序列化为 List<List<int>>
或 int[][]
会起作用,但我非常不想这样做。
【问题讨论】:
Json 中的Triangles
属性是一个数组数组。你可以这样修复它:public List<List<int>> Triangles get; set;
您的类的序列化结果将类似于"Triangles":["Indices":[1,2],"Indices":[3],"Indices":[4]]
。您必须反序列化为 List<List<int>>
并通过简单的选择选择正确的类或编写自定义解析器。
你所拥有的是一个int数组。序列化的字符串应该更像"Triangles":["Indices":[1,2,3],"Indices":[1,2,3],"Indices":[1,2,3]]
@DragandDrop 我错过了补充说,出于语义原因,我更愿意将三角形保留为一个类。我想自定义解析器是我必须采用的方式。
一个代表你得到的数据的类。一个类来表示您将使用的数据。我建议在两者之间进行选择。自定义解析器可能很难。我很确定我的记事本中有一个类似的解析器问题,但我找不到。
【参考方案1】:
使用自定义转换器。将数组反序列化为 JArray 并从中选择。
var json = " \"Triangles\": [[1337,1400],[1338],[1339]]";
var mesh = JsonConvert.DeserializeObject<Mesh>(json);
public class Mesh
[JsonConverter(typeof(MyConverter))]
public Triangle[] Triangles get; set;
public class Triangle
[JsonProperty]
public int[] Indices get; set;
public class MyConverter : JsonConverter
public override bool CanConvert(Type objectType)
return true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
return null;
var result =
JArray.Load(reader)
.Select(x =>
new Triangle Indices = x.Select(y => (int)y).ToArray()
);
return result.ToArray();
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
【讨论】:
【参考方案2】:您的课程目前的设置方式。 JSON.NET 将尝试将 Triangle[]
反序列化为 json 对象数组。最简单的解决方案是将Triangles
的类型更改为int[,]
,使其成为二维数组。如果您想继续使用Triangle[]
,您需要使用自定义JsonConverter
。
编辑:由于您想保留 Triangle 类,您需要一个自定义的 JsonConverter
类。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class TriangleJsonConverter : JsonConverter<Triangle>
// Called when Triangle is written
public override void WriteJson(JsonWriter writer, Triangle value, JsonSerializer serializer)
// Uses JsonSerializer to write the int[] to the JsonWriter
serializer.Serialize(writer, value.Indices);
// Called when Triangle is read
public override Triangle ReadJson(JsonReader reader, Type objectType, Triangle existingValue, bool hasExistingValue, JsonSerializer serializer)
// Reads a json array (JArray) from the JsonReader
var array = JArray.Load(reader);
// Creates a new Triangle.
return new Triangle
// converts the json array to an int[]
Indices = array.ToObject<int[]>()
;
要告诉 JSON.NET 使用TriangleJsonConverter
,您需要将JaonArray
应用于Triangles
字段而不是JsonProperty
。
public class Mesh
[JsonArray(ItemConverterType = typeof(TriangleJsonConverter))]
public Triangle[] Triangles get; set;
【讨论】:
还在JsonProperty
:[JsonProperty(ItemConverterType = typeof(TriangleJsonConverter))]
以上是关于使用 Newtonsoft 反序列化未命名数组的 JSON 数组的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Newtonsoft.Json 反序列化 JSON 数组
如何使用 Newtonsoft.Json 正确反序列化数组中的嵌套对象? [复制]
Newtonsoft.JSON 在反序列化数组中被双引号包围的对象时窒息