I am using Visual Studio's auto generated REST Web Application project structure to create a RESTful API that consumes a JSON input.
Without going into too much detail, I have attempted to define a JSON structure like these:
Example 1:
"operation": {
"type": "EXIST",
"args": [
{
"ColumnName": "SomeColumnA",
"Row": 2
}
]
}
Example 2:
"operation": {
"type": "ADD",
"args": [
{
"type": "ADD",
"args": [
{
"columnName": "SomeColumnB",
"row": 12
},
{
"columnName": "SomeColumnC",
"row": 18
}
]
},
20
]
}
operation
represents one of any number of basic database operations and the arguments for those operations. In my first example, the operation is EXIST
, which should check a database cell to see if a value exists or not. The args
for this operation is simply an object that contains the column and row information for the cell to check (I call this a Value
). In my second example, the function is ADD
, which should add two values together and return the sum. Here, the arguments are a constant of 20 and a nested ADD
function, which itself takes two Values
. So, in general, the args
array can take either primitive values, another nested operation
, or a pair of values that represents a cell to read the actual value from. The ultimate goal here is to create a general structure that would allow me to nest combinations of functions, cell values, and constants to create compound functions like Average
or Sum
.
In my Models folder, I have the following classes to cast my data to:
public class Instruction
{
public Operation[] Operations { get; set; }
}
public class Operation
{
public string Type { get; set; }
public object[] Args { get; set; }
}
public class Value
{
public string ColumnName { get; set; }
public int Row { get; set; }
}
Note that the Args
in Operation
is of type object[]
.
When I call my web application by POSTing this JSON to it, C# automatically parses the JSON into objects defined in my Models folder. Say we used Example 1:
[HttpPost]
public IHttpActionResult Foo(Instruction instruction)
{
foreach(Operation op in instruction.Operations) {
switch (op.Type) {
case "EXIST":
Console.WriteLine("exist"); // works fine
// since we got here, expect Args[0] to be type 'Value'
var value = (Value) op.Args[0]; // InvalidCastException
// logic for EXIST
case "ADD":
// logic for ADD
// ...
}
}
}
It's casting Operation
just fine, and I get Type
out correctly. I also get Args
as an object[]
with a lone element in it. But if I try to cast it to Value
, it refuses to cast properly.
My question after all of this is: what is the best way to achieve what it looks like I'm attempting to do here? Am I on the right track? If so, what is my error? If I'm going about this the wrong way, what is a better practice alternative? Note that since I'm using Visual Studio's out-of-the-box Web Application framework I don't seem to have access to the function that deseralizes the JSON, so I don't think I can build a custom deserializer.