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();
}
}
To use the converter, create an instance and add it to the serializer's Converters
collection before you deserialize:
serializer.Converters.Add(new ChipConverter());
Or if you prefer, you can annotate your class with a [JsonConverter]
attribute instead:
[JsonConverter(typeof(ChipConverter))]
class Chip
{
...
}
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();
}
}
}
Output:
gates: 1
False, True
gates: 2
False, False
False, True