为什么我的Web API控制器操作不反序列化子属性的子属性?

时间:2014-08-14 17:05:41

标签: json asp.net-web-api frombodyattribute

我正在将PUT请求中的json有效负载发送到Web API控制器操作。有问题的行为有一个如下所示的签名:

public IHttpActionResult Post([FromBody]SaveThingRequest request)

SaveThingRequest看起来像这样:

public class SaveThingRequest
{
    public List<ElementInfo> Elements { get; set; }

    public class ElementInfo
    {
        public List<ElementSettingInfo> Settings { get; set; }

        public class ElementSettingInfo
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }
    }
}

我在包含具有“设置”的元素的请求正文中发布了json。我通过在控制器操作中手动反序列化并确认JSON具有类似于以下内容的结构来证实这一点:

{
    Elements: [
        {
            Settings: [
                {
                    Name: 'Name 1',
                    Value: 'Value 1'
                },
                {
                    Name: 'Name 2',
                    Value: 'Value 2'
                }
            ]
        },
        {
            Settings: [
                {
                    Name: 'Name 1',
                    Value: 'Value 1'
                },
                {
                    Name: 'Name 2',
                    Value: 'Value 2'
                }
            ]
        }
    ]
}

但是,当.NET反序列化有效负载并创建SaveThingRequest时,我的元素将被填充,但所有元素都具有空的Settings属性。我不知道怎么解决这个问题。有没有人对这里发生的事情有任何想法?

4 个答案:

答案 0 :(得分:14)

应删除此问题。它像宣传的那样工作。我的问题是我在JSON上有一个名为&#39; settings&#39; (小写)反序列化程序试图匹配,因为如果找不到区分大小写的情况,NewtonSoft反序列化会尝试非区分大小写的匹配。通过将方法的签名更改为:

,我能够发现发生了什么
public IHttpActionResult Post([FromBody]object request)

然后将其添加到方法实现中:

var result = JsonConvert.DeserializeObject<SaveThingRequest>(request.ToString());

我有一个反序列化例外说:

  

无法反序列化当前的JSON对象(例如{&#34; name&#34;:&#34; value&#34;})   进入类型   &#39; System.Collections.Generic.List`1 [Noteable.Contracts.ClinicalReports.SaveThingRequest + ElementInfo + ElementSettingInfo]&#39;   因为该类型需要一个JSON数组(例如[1,2,3])来反序列化   正确。要修复此错误,请将JSON更改为JSON数组   (例如[1,2,3])或更改反序列化类型以使其正常   .NET类型(例如,不是整数的基本类型,不是集合   类似于数组或List的类型,可以从JSON反序列化   宾语。 JsonObjectAttribute也可以添加到类型中以强制它   从JSON对象反序列化。路径   &#39; Elements [0] .settings.TextSize&#39;,第11行,第20位。

消息的结尾向我展示了当反序列化器失败并将我指向正确方向时反序列化的内容。 = [

答案 1 :(得分:4)

我遇到了同样的问题。然而,问题还是别的。

在我的例子中,声明没有获取序列化的属性没有公共访问说明符。我向公众宣布,它完全没问题。

希望这能帮助陷入困境的人。我花了20分钟才达到这个解决方案。

答案 2 :(得分:0)

确保你没有像我那样做一些愚蠢的事情,并从浏览器而不是JSON对象发送部分'字符串化'的JSON字符串。

看到问题?直到我尝试从字符串反序列化它之后我才意识到shippingAddress本身是一个字符串而不是一个真正的JSON对象。该对象的其余部分是正确的JSON,但我不小心序列化了shippingAddress字段。

{   “fspID”:571285,   “foo”:444,   “shippingAddress”:“{\”countryCode \“:\”US \“,\”firstName \“:\”Test User \“,\”lastName \“:null,\”add​​ress1 \“:\”1 Main St4 \“,\”add​​ress2 \“:null,\”company \“:null,\”city \“:\”San Jose \“,\”stateOrProvince \“:\”California \“,\”stateCd \“: \“CA \”,\“zipOrPostal \”:\“95131 \”,\“countryName \”:\“美国\”,\“countryDesc \”:\“美国\”,\“手机\”:空,\ “PHONE2 \”:空}” }

答案 3 :(得分:0)

如果您使用JSON.NET和属性[JsonProperty]来命名属性 - 请确保您没有意外地复制粘贴相同的属性两次而忘记更新字符串值。

 [JsonProperty("billingAddress")]
 public Address BillingAddress { get;set; }

 [JsonProperty("billingAddress")]
 public Address ShippingAddress { get;set; }

这将抛出一个实际上不会被您看到的Newtonsoft.Json.JsonSerializationException并且会搞砸模型。