Json.net反序列化到JSon中可能包含数组或嵌套数组的对象 [英] Json.net deserialising to objects from JSon that may contain either an array, or a nested array

查看:110
本文介绍了Json.net反序列化到JSon中可能包含数组或嵌套数组的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有许多正在使用

JsonSerializer serializer = new JsonSerializer(); t obj = (t)serializer.Deserialize(file, typeof(t));

JsonSerializer serializer = new JsonSerializer(); t obj = (t)serializer.Deserialize(file, typeof(t));

到对象的集合.除其他外,它们包含以下数据. 真表"中的数组数取决于门"的值

to a collection of objects. They contain, amongst other things the following data. The number of arrays in "truthtable" is determined by the value of "gates"

"gates" : 1,
"truthtable" : [ false, true ]

"gates" : 2,
"truthtable" : [ [ false, false ], [ false, true ] ]

如果我尝试将"truthtable"反序列化为以下属性,则示例1失败.

if I try to deserialise "truthtable" to the following property, example 1 fails.

public List<List<bool>>truthtable { get; set; }

有什么办法可以将这两种不同类型的真值表反序列化到同一对象?我曾尝试构建自定义反序列化器,但Json都将其视为"JsonToken.StartArray",因此无法以这种方式进行区分.

Is there any way I can deserialise these two different types of truthtable to the same object? I've tried building a custom deserialiser, but Json sees both as "JsonToken.StartArray", so can't differentiate that way.

理想情况下,我希望能够对两个示例进行反序列化,就好像它们是布尔数组的数组一样.

Ideally, I'd like to be able to deserialise both examples as if they were arrays of arrays of booleans.

修改 应该提到的是,我无法更改Json文件的创建方式.我无权访问他们的作品.

Edit Should have mentioned, I cannot alter the way the Json files are created. I don't have access to their creation.

推荐答案

可以使用自定义JsonConverter解决此问题.转换器可以读取门数,然后相应地填充List<List<bool>>.如果只有一个门,则可以将单个列表包装在外部列表中,以使其与您的班级一起使用.

This problem can be solved using a custom JsonConverter. The converter can read the number of gates and then populate the List<List<bool>> accordingly. If there is only one gate, it can wrap the single list in an outer list to make it work with your class.

假设您要反序列化的类如下所示:

Assuming the class that you are trying to deserialize into looks something like this:

class Chip
{
    public int Gates { get; set; }
    public List<List<bool>> TruthTable { get; set; }
}

然后转换器可能看起来像这样:

then the converter might look something like this:

class ChipConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Chip));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);

        Chip chip = new Chip();
        chip.Gates = (int)jo["gates"];
        JArray ja = (JArray)jo["truthtable"];

        if (chip.Gates == 1)
        {
            chip.TruthTable = new List<List<bool>>();
            chip.TruthTable.Add(ja.ToObject<List<bool>>());
        }
        else
        {
            chip.TruthTable = ja.ToObject<List<List<bool>>>();
        }

        return chip;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,请创建一个实例并将其添加到序列化器的Converters集合中,然后再反序列化:

To use the converter, create an instance and add it to the serializer's Converters collection before you deserialize:

serializer.Converters.Add(new ChipConverter());

或者,如果愿意,可以使用[JsonConverter]属性来注释您的班级:

Or if you prefer, you can annotate your class with a [JsonConverter] attribute instead:

[JsonConverter(typeof(ChipConverter))]
class Chip
{
    ...
}

这里是一个演示转换器运行的演示(请注意,此处我使用JsonConvert.DeserializeObject<T>()而不是创建JsonSerializer实例,但其工作方式相同):

Here's a demo showing the converter in action (note I used JsonConvert.DeserializeObject<T>() here instead of creating a JsonSerializer instance, but it works the same way):

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        [
            {
                ""gates"": 1,
                ""truthtable"": [ false, true ]
            },
            {
                ""gates"": 2,
                ""truthtable"": [ [ false, false ], [ false, true ] ]
            }
        ]";

        List<Chip> chips = JsonConvert.DeserializeObject<List<Chip>>(json,
                                                         new ChipConverter());

        foreach (Chip c in chips)
        {
            Console.WriteLine("gates: " + c.Gates);
            foreach (List<bool> list in c.TruthTable)
            {
                Console.WriteLine(string.Join(", ",
                    list.Select(b => b.ToString()).ToArray()));
            }
            Console.WriteLine();
        }
    }
}

输出:

gates: 1
False, True

gates: 2
False, False
False, True

这篇关于Json.net反序列化到JSon中可能包含数组或嵌套数组的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆