反序列化数组的 JSON 数组



我有以下 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);

示例小提琴。

相关内容

  • 没有找到相关文章

最新更新