【发布时间】:2017-04-03 02:18:32
【问题描述】:
我正在使用 Visual Studio 的自动生成的 REST Web 应用程序项目结构来创建一个使用 JSON 输入的 RESTful API。
没有过多的细节,我尝试定义一个像这样的 JSON 结构:
示例 1:
"operation": {
"type": "EXIST",
"args": [
{
"ColumnName": "SomeColumnA",
"Row": 2
}
]
}
示例 2:
"operation": {
"type": "ADD",
"args": [
{
"type": "ADD",
"args": [
{
"columnName": "SomeColumnB",
"row": 12
},
{
"columnName": "SomeColumnC",
"row": 18
}
]
},
20
]
}
operation 表示任意数量的基本数据库操作之一以及这些操作的参数。在我的第一个示例中,操作是EXIST,它应该检查数据库单元以查看值是否存在。此操作的args 只是一个对象,其中包含要检查的单元格的列和行信息(我称之为Value)。在我的第二个示例中,函数是ADD,它应该将两个值相加并返回总和。这里,参数是一个常量 20 和一个嵌套的 ADD 函数,它本身需要两个 Values。因此,一般来说,args 数组可以采用原始值、另一个嵌套的 operation 或一对表示要从中读取实际值的单元格的值。这里的最终目标是创建一个通用结构,允许我嵌套函数、单元格值和常量的组合,以创建像 Average 或 Sum 这样的复合函数。
在我的模型文件夹中,我有以下类可以将我的数据转换为:
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; }
}
注意Operation 中的Args 是object[] 类型。
当我通过 POST 这个 JSON 来调用我的 Web 应用程序时,C# 会自动将 JSON 解析为我的模型文件夹中定义的对象。假设我们使用了示例 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
// ...
}
}
}
它正在投射Operation 就好了,我正确地得到了Type。我还得到Args 作为object[],其中有一个单独的元素。但如果我尝试将其转换为 Value,它会拒绝正确转换。
在这一切之后,我的问题是:实现我在这里尝试做的最好方法是什么?我在正确的轨道上吗?如果是这样,我的错误是什么?如果我以错误的方式解决这个问题,那么更好的做法是什么?请注意,由于我使用的是 Visual Studio 的开箱即用 Web 应用程序框架,我似乎无法访问反序列化 JSON 的函数,因此我认为我无法构建自定义反序列化器。
【问题讨论】:
-
除非您尝试遵循一些已经发布的 JSON 有效负载规范,否则为什么不首先定义您的类并使用众多类到 JSON 预览工具之一呢?这样你就知道在反序列化期间很可能不会有任何问题。 XML也是一样,我比较懒,总是先创建类
-
要转换哪个 JSON 数组?Example1 与 Example2 不同
-
如果将 Args 定义为
public Value[] Args{get;set;}会发生什么?还要查看 C# 中的动态类型。您可以在 Operation 模型中将 Args 定义为public dynamic Args{get;set;}。从那里您可以直接使用Args[0].row,而无需其他模型。 -
@garethb - 我无法将类型设置为
Value[],因为该数组可能包含int、string、double、bool、Value或 @ 987654353@。我无法提前知道它是哪种类型,我只能在运行时检查它并执行正确的转换。 -
@Fawfulcopter 在这种情况下,我会将 Args 定义为动态的。