【问题标题】:Some property doesn't get serialized when returned in a Web API action在 Web API 操作中返回时,某些属性未序列化
【发布时间】:2016-07-26 15:47:25
【问题描述】:

问题在于以下类:

[DebuggerDisplay("{Kind}: {Identifier}")]
public class SocialConnection
{
    public virtual Guid UniqueId
    {
        get { return Id; }
        set { Id = value; }
    }

    // SocialConnectionKind is an enumeration
    public virtual SocialConnectionKind Kind { get; set; }

    public virtual string Identifier { get; set; }
}

Kind 属性永远不会被序列化:当我请求一个具有关联 SocialConnection 的对象时,我永远不会得到整个属性。

顺便说一句,如果我手动调用JsonConvert.SerializeObject,它会被序列化。它应该是默认媒体类型格式化程序的东西,但到目前为止我无法弄清楚解决方案。

【问题讨论】:

  • 请粘贴预期结果和当前结果,以便更清晰。我明白了,你 Json 序列化 SocialConnection 对象并且不接收 SocialConnectionKind 枚举,否则会在 JsonConvert.SerializeObject 上序列化
  • @MrinalKamboj 你理解正确
  • @MrinalKamboj BTW 我认为这个问题很愚蠢,我要检查问题背后的原因
  • 看起来确实是个很奇怪的问题:)
  • @MrinalKamboj 我已经找到了导致问题的原因,我会自己回答......你会笑很多;P

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


【解决方案1】:

导致此序列化问题的问题非常简单。检查SocialConnectionKind枚举:

public enum SocialConnectionKind
{
    Skype,
    Facebook,
    Twitter,
    LinkedIn,
    Hangouts
}

您是否已经注意到可能是什么问题?如果值是除Skype 之外的任何值,则不会重现该问题!

为什么?枚举以0 开头,看看我是如何配置我的WebAPI 的HttpConfiguration:

config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling =
                                                           DefaultValueHandling.Ignore;

Enum 默认基础类型int 的默认值是多少?是的,它是0。

那么,是什么解决了这个问题?

public enum SocialConnectionKind
{
    Skype = 1, // <--- The issue was solved starting the enumeration from 1!
    Facebook,
    Twitter,
    LinkedIn,
    Hangouts
}

另一种方法

正如@Avner Shahar-Kashtan 在一些评论中指出的那样,我也可以使用[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] 属性来解决这个问题:

[DebuggerDisplay("{Kind}: {Identifier}")]
public class SocialConnection
{
    public virtual Guid UniqueId
    {
        get { return Id; }
        set { Id = value; }
    }

    // SocialConnectionKind is an enumeration
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
    public virtual SocialConnectionKind Kind { get; set; }

    public virtual string Identifier { get; set; }
}

...这样就不需要从1开始枚举。

无论如何,在我的特殊情况下,我更喜欢从1开始方法,因为我发现更清洁的方法是避免使用序列化特定属性污染我的POCO,因为SocialConnection类存在于共享库,这个序列化问题是具体项目中的实现问题。

【讨论】:

  • 有趣的场景。但是 deserializer 不会有类似的设置,如果不包含该值,则将属性初始化为 0/Skype 吗?或者反序列化代码不是 C#/.NET,所以你实际上没有 SocialConnection 类。
  • @AvnerShahar-Kashtan 好吧,在那种情况下,如果我没记错的话,它会设置值,整个设置是特定于序列化的。
  • @AvnerShahar-Kashtan 啊,你是对的。现在,我正在使用 C# 集成测试 (VSTest) 测试我的控制器,顺便说一句,消费者将是 Web 浏览器,因此它不会收到 0,并且使用 JavaScript 我需要检查如果属性kind 在那里。我宁愿避免这种情况并从1 开始以避免检查。社交关系必须具有种类。
  • @MatíasFidemraizer 是的,但是如果删除默认值的最终结果是 0 - 也就是说,序列化器和反序列化器都可以处理它并保持数据完整性 - 那么这不是 问题 i> 但一个实现细节。一个令人困惑和令人惊讶的,真实的。 :)
  • 但是,如果您的客户端不使用相同的反序列化器和环境(即 javascript)并且无法在丢失数据的情况下保持数据完整性(它不能),那么它肯定会成为一个问题。顺便说一句,简单地不忽略默认值而不是更改您的枚举值不是更清楚吗?
猜你喜欢
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
相关资源
最近更新 更多