I have this json:
var x = [
[99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}],
[7,"x","date"],
[60,"x","1dp",{"GroupNum": 1}],
...
]
The following rules exist (let i
refer to the inner list index):
x[i][0]
- mandatory item - always an integerx[i][1]
- mandatory item - always a stringx[i][2]
- mandatory item - always a stringx[i][3]
- optional item - when it exists then it has the following rules:x[i][3].GroupNum
- mandatory field - always an integerx[i][3].Total
- optional field - when it exists then it is a list of integers
So I have created the following classes for these rules:
public class ReportTemplateField : System.Collections.CollectionBase
{
public object this[int index]
{
get
{
switch (index)
{
case 0:
return (int)List[index];
case 1:
case 2:
return (string)List[index];
case 3:
return (ReportGrouping)List[index];
default:
throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items");
}
}
set
{
switch (Count)
{
case 0:
List[index] = unchecked((int)value);
break;
case 1:
case 2:
List[index] = (string)value;
break;
case 3:
List[index] = (ReportGrouping)value;
break;
default:
throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items");
}
}
}
public void Add(object item)
{
switch (Count)
{
case 0:
List.Add(unchecked((int)item));
break;
case 1:
case 2:
List.Add((string)item);
break;
case 3:
List.Add((ReportGrouping)item);
break;
default:
throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items");
}
}
}
public class ReportGrouping
{
public int GroupNum { get; set; }
public List<int> Total { get; set; }
}
However, when I attempt to deserialize using json.net, the ReportTemplateField
class never gets used. I know this because I have put breakpoints in every method and none of them get triggered:
string json = "[[99,\"abc\",\"2dp\",{\"GroupNum\": 0,\"Total\":[4, 1]}],[7,\"x\",\"date\"],[60,\"x\",\"1dp\",{\"GroupNum\": 1}]]";
List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json);
int Total01 = parsed[0][3].Total[1];
gives me this error:
error CS1061: 'object' does not contain a definition for 'Total' and no extension method 'Total' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
However it works if I just deserialize the ReportGrouping
in isolation:
string json2 = "{\"GroupNum\": 0,\"Total\":[4, 1]}";
ReportGrouping parsed2 = JsonConvert.DeserializeObject<ReportGrouping>(json2);
parsed2.Total[1]; // 1
So the problem lies with the ReportTemplateField
class. Maybe I shouldn't be inheriting from System.Collections.CollectionBase
? I basically followed this walkthough with some modifications - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx but it does say that the documentation may be outdated. I'm using .NET 4.5 so please factor that into any your answers.
How can I get Json.net to deserialize correctly, so that I can just go parsed[0][3].Total[1];
to access the integer value of the second total without needing to cast it or do anything to it at all?