2

我正在编写一个带有几个接收 JSON 数据的 PUT 方法的 Web API ApiController。JSON 不是确定性的,因此不能硬映射到自定义 C# 对象,但需要作为字典/序列(映射/列表)接收。

我已经尝试在控制器中为 PUT 方法的数据参数使用 IDictionary,并且这种工作 - 数据似乎从 JSON 映射到字典。但是,有必要将字典声明为<String,Object>,并且没有明确的方法可以将 Object 值检索为其适当的类型。(我在搜索中发现了一些建议的 kluges,但它们就是这样。)

还有一个 System.Json.JsonObject 类型,我终于设法通过 NuGet 加载它,但是当我使用它时,系统似乎不知道如何映射数据。

这通常是如何完成的?如何实现接收通用 JSON 的 ApiController 方法?

我可以看到三种基本方法:

  1. 不知何故使字典/序列与对象或类似的东西一起工作。
  2. 使 System.Json.JsonObject 之类的东西工作,也许是通过调整路由信息。
  3. 将 JSON 作为字节数组接收,然后使用可用的 C# JSON 工具包之一显式解析。

(关于数据的动态程度,JSON 对象可能缺少条目或无关条目,在某些情况下,特定条目可能表示为单个 JSON 值或 JSON 值数组。(其中“值”是 JSON 数组、对象、字符串、数字、布尔值或空值。)一般来说,除了数组/非数组的歧义之外,键和值类型之间的关系是已知的。)

(但我应该注意,这是一个大型项目,我将从其他作者的几个其他组件接收 JSON 字符串。能够检查接收到的类型并断言它是预期的将非常有用,甚至可能是必要的从安全的角度来看。)

(我应该补充一点,我是 C# 的相对新手——只使用了大约 6 个月。)

4

1 回答 1

0

你必须知道你期待什么样的数据,但我过去使用动态类型成功地做到了这一点。

像这样的东西:

    [Test]
    public void JsonTester()
    {
        string json = "{ 'fruit':'banana', 'color':'yellow' }";

        dynamic data = JsonConvert.DeserializeObject(json);

        string fruit = data["fruit"];
        string color = data["color"];

        Assert.That(fruit == "banana");
        Assert.That(color == "yellow");
    }

编辑:
您要么需要事先知道要反序列化的类型 - 在这种情况下,您可以立即将其反序列化为该类型。
或者您可以将其反序列化为一种dynamic类型,然后在您知道要使用它做什么后将其转换为您的静态类型。

using Newtonsoft.Json;
using NUnit.Framework;

public class DTO
{
    public string Field1;
    public int Field2;
}

public class JsonDeserializationTests
{
    [Test]
    public void JsonCanBeDeserializedToDTO()
    {
        string json = "{ 'Field1':'some text', 'Field2':45 }";

        var data = JsonConvert.DeserializeObject<DTO>(json);

        Assert.That(data.Field1 == "some text");
        Assert.That(data.Field2 == 45);
    }

    [Test]
    public void JsonCanBeDeserializedToDynamic_AndConvertedToDTO()
    {
        string json = "{ 'Field1':'some text', 'Field2':45 }";

        var dynamicData = JsonConvert.DeserializeObject<dynamic>(json);
        var data = new DTO { Field1 = dynamicData["Field1"], Field2 = dynamicData["Field2"] };

        Assert.That(data.Field1 == "some text");
        Assert.That(data.Field2 == 45);
    }
}
于 2014-06-03T22:54:51.713 回答