如何将JSON数据接收到Web API ApiController方法中?

时间:2014-06-03 22:50:45

标签: c# json asp.net-web-api asp.net-apicontroller

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

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

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

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

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

  1. 以某种方式使字典/序列与Object或其他类似。
  2. 制作像System.Json.JsonObject这样的东西,可能是通过调整路由信息。
  3. 将JSON作为字节数组接收,然后使用其中一个可用的C#JSON工具包进行显式解析。
  4. (关于数据的动态性,JSON对象可能缺少条目或无关条目,在某些情况下,特定条目可能表示为单个JSON值或JSON数组值。(其中“value”是JSON数组,对象,字符串,数字,布尔值或null。)通常,除了数组/非数组歧义外,键和值类型之间的关系是已知的。)

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

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

1 个答案:

答案 0 :(得分: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);
    }
}