反序列化数组的 JSON 数组
本文关键字:数组 JSON 反序列化 | 更新日期: 2023-09-27 17:57:22
我有以下 JSON 数据,我想将其反序列化为 C# POCO 对象,但我在反序列化数组数组时遇到问题。
var json = @"{
""name"": ""Foo"",
""pages"": [
{
""page"": 1,
""fields"": [
{
""name"": ""stuffs"",
""rows"": [
[{ ""value"" : ""$199""}, { ""value"": ""foo"" }],
[{ ""value"" : ""$222""}, { ""value"": ""bar"", ""color"": ""blue"" }]
]
}]
}
]
}";
例外情况是
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'UserQuery+TableRow' 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 'rows[0]', line 4, position 5.
按照异常消息的建议,我确实尝试了所有这些事情,但只是面临更多错误。
这些是我的 POCO 对象
public class Document
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("pages")]
public Page[] Pages { get; set; }
}
public class Page
{
[JsonProperty("page")]
public int PageNumber { get; set; }
[JsonProperty("fields")]
public FieldBase[] FieldsBase { get; set; }
}
public class TableRow
{
public Cell[] Cells { get; set; }
}
public class Cell
{
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("color")]
public string Color { get; set; }
}
public abstract class FieldBase
{
[JsonProperty("name")]
public string Name { get; set; }
}
public class Table : FieldBase
{
[JsonProperty("rows")]
public TableRow[] Rows { get; set; } = new TableRow[0];
}
和我的字段转换器来处理抽象类(不确定这是否重要)
public class FieldConverter : JsonConverter
{
static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() };
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(FieldBase));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
return JsonConvert.DeserializeObject<Table>(jo.ToString(), SpecifiedSubclassConversion);
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // won't be called because CanWrite returns false
}
}
public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(FieldBase).IsAssignableFrom(objectType) && !objectType.IsAbstract)
return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
return base.ResolveContractConverter(objectType);
}
}
下面的代码行,在 LINQPad 中执行时,会产生错误
JsonConvert.DeserializeObject<Document>(json, new FieldConverter()).Dump();
任何帮助将不胜感激。
在你的 json 中,"rows"
是一个交错数组:
"rows": [[{ "value" : "$199"}, { "value": "foo" }]]
但是,在对象模型中,这对应于包含单元格数组的TableRow
类数组。 因此,您将需要另一个JsonConverter
将每个TableRow
序列化为单元格数组而不是对象:
public class TableRowConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TableRow);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var cells = serializer.Deserialize<Cell[]>(reader);
return new TableRow { Cells = cells };
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var row = (TableRow)value;
serializer.Serialize(writer, row.Cells);
}
}
public class JsonDerivedTypeConverter<TBase, TDerived> : JsonConverter where TDerived : TBase
{
public JsonDerivedTypeConverter()
{
if (typeof(TBase) == typeof(TDerived))
throw new InvalidOperationException("TBase and TDerived cannot be identical");
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TBase);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<TDerived>(reader);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后,要反序列化,请执行以下操作:
var settings = new JsonSerializerSettings
{
Converters = new JsonConverter[] { new TableRowConverter(), new JsonDerivedTypeConverter<FieldBase, Table>() },
};
var doc = JsonConvert.DeserializeObject<Document>(json, settings);
示例小提琴。