【问题标题】:Why is my Web API controller action not deserializing child properties of child properties?为什么我的 Web API 控制器操作没有反序列化子属性的子属性?
【发布时间】:2021-08-26 17:26:47
【问题描述】:

我正在将 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 时,我的元素被填充,但它们都有一个空设置属性。我不知道如何解决这个问题。有人对这里可能发生的事情有任何想法吗?

【问题讨论】:

  • 将您的有效负载粘贴到问题中。 Nm,我瞎了。
  • 我遇到了同样的问题。然而,问题是别的。就我而言,未序列化的属性没有默认构造函数。

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


【解决方案1】:

这个问题应该被删除。它像宣传的那样工作。我的问题是我在 JSON 上有一个名为“设置”(小写)的附加属性,反序列化程序试图匹配该属性,因为如果未找到区分大小写的匹配,NewtonSoft 反序列化会尝试不区分大小写的匹配。我能够通过将方法的签名更改为:

public IHttpActionResult Post([FromBody]object request)

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

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

我得到一个反序列化异常说:

无法反序列化当前 JSON 对象(例如 {"name":"value"}) 输入类型 'System.Collections.Generic.List`1[Noteable.Contracts.ClinicalReports.SaveThingRequest+ElementInfo+ElementSettingInfo]' 因为该类型需要一个 JSON 数组(例如 [1,2,3])来反序列化 正确。要修复此错误,请将 JSON 更改为 JSON 数组 (例如 [1,2,3])或更改反序列化类型,使其成为正常的 .NET 类型(例如,不是像整数这样的原始类型,也不是集合 可以从 JSON 反序列化的数组或列表等类型 目的。 JsonObjectAttribute 也可以添加到类型中来强制它 从 JSON 对象反序列化。小路 'Elements[0].settings.TextSize',第 11 行,位置 20。

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

【讨论】:

  • 我有一个类似的场景,复杂的对象类型没有在 webapi 请求反序列化器上被适当地反序列化。我使用此解决方案来调试问题并更正序列化过程。是的,WebAPI 正在做它应该做的事情,但它也没有为我提供一个理由或方法来专门解决我需要的更改。谢谢
  • 这是找到问题真正根源的非常有用的方法。知道如何在发生时捕获真正的底层 JSON 异常吗?
  • 这是一个非常好的解决方案,可以帮助您调试 Web api 的反序列化问题。
  • 真正的 stackoverflow 是当你回答自己的问题并为每个人提供有价值的调试方法时。
  • 这对我帮助很大。感谢您提供这种故障排除方法。
【解决方案2】:

我遇到了同样的问题。但是,问题出在其他地方。

在我的例子中,未序列化的属性是在没有公共访问说明符的情况下声明的。我向公众宣布了它,它运行得很好。

希望这会帮助陷入这种情况的人。我花了 20 分钟才找到这个解决方案。

【讨论】:

  • 谢谢!如果它能给你一些指示就好了!
【解决方案3】:

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

看到问题了吗?起初我没有,直到我尝试从字符串反序列化它,然后我意识到shippingAddress 本身是一个字符串,而不是一个实际的 JSON 对象。对象的其余部分是正确的 JSON,但我不小心序列化了 shippingAddress 字段。

{ “fspID”:571285, “富”:444, "shippingAddress": "{\"countryCode\":\"US\",\"firstName\":\"Test User\",\"lastName\":null,\"address1\":\"1 Main St4 \",\"address2\":null,\"company\":null,\"city\":\"San Jose\",\"stateOrProvince\":\"California\",\"stateCd\": \"CA\",\"zipOrPostal\":\"95131\",\"countryName\":\"United States\",\"countryDesc\":\"United States\",\"phone\":空,\"phone2\":null}" }

【讨论】:

    【解决方案4】:

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

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

    这会抛出一个Newtonsoft.Json.JsonSerializationException,你实际上看不到它,并且会搞砸模型。

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,即子属性为空。然而问题是别的。

      我在该属性上只有一个 getter,一旦我也添加了一个 setter,那么该属性就按预期设置了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-04
        • 2015-04-12
        • 1970-01-01
        • 2013-04-10
        • 2015-09-10
        • 2010-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多