【问题标题】:system.text.json explicitly set null attributes while ignoring unset attributes when serializingsystem.text.json 显式设置 null 属性,同时在序列化时忽略未设置的属性
【发布时间】:2020-10-30 11:53:36
【问题描述】:

我正在尝试将 POCO 对象序列化为更新请求。

我未设置的值被序列化为 null,这导致它们被更新为 null。

如果我将 IgnoreNullValues 设置为 true,则可以解决问题。但是,没有办法将属性显式更新为 null。

我认为解决这个问题的方法是创建一个自定义的 null 对象,该对象序列化为 null 并忽略真正的 null 值。这可能吗?我还能如何解决这个问题?

编辑:添加了我尝试序列化的 POCO 请求对象的示例

internal class ContactCreateRequest
{
   [JsonPropertyName("contact")]
   public ContactEntity Contact { get; set; }
}

internal class ContactEntity
{
    public string CompanyName { get; set; }
    public DateTime? CreateDateTime { get; set; }
    public string CreateId { get; set; }
    public string Department { get; set; }
    public string DisplayName { get; set; }
    public string FirstName { get; set; }
    public string GoesBy { get; set; }
    public string Id { get; set; }
    public string JobTitle { get; set; }
    public DateTime? LastEditDateTime { get; set; }
    public string LastEditId { get; set; }
    public string LastName { get; set; }
    public string ParentId { get; set; }
    public string Title { get; set; }
    public string UpdateAction { get; set; }
}

我想要以下

var request = new ContactCreateRequest
{
   Contact = new ContactEntity
   {
      LastName = "Jane",
      JobTitle = null,
      UpdateAction = "Update"
   }
}

{"contact": {"LastName": "Jane", "JobTitle": null, "UpdateAction": "Update"}}

...但是这当然行不通,因为所有未设置的字段也是空的,因此它们与 JobTitle 相同。这就是为什么我想知道是否需要使用空对象模式来定义 JobTitle 应该显式设置为空。

【问题讨论】:

  • 这是PATCH REST 请求吗?
  • 遗憾的是,我正在使用外部 api,它的行为很奇怪。
  • 您能提供一个示例 POCO 吗?这将有助于使答案更直接相关。
  • 所以要发送更新,将部门更改为“营销”,将 Title 设置为 null,并且不影响其他任何内容,您应该发送 {"contact":{"Department":"Marketing","Title":null}}... 对吗?
  • @madreflection 是的,这就是 API 的工作原理

标签: c# serialization null system.text.json null-object-pattern


【解决方案1】:

编辑:由于 dbc 的注释非常恰当,我已将“null”值更改为“null_null”以避免处理“Null”姓氏时出现问题。

您可以通过创建自定义 JSON 转换器、为字符串属性分配“null"null_null" 值而不是 null 并使用 IgnoreNullValues 选项来实现您的目标。 JSON 序列化程序将忽略所有未初始化的值,自定义转换器将序列化您的 "null" "null_null" 值,就好像它是 null。如果您想要其他类型的类似功能,例如您的 DateTime,那么您需要添加一个新的 DateTime JsonConverter 或创建一个更通用且可以处理所有可能情况的 JsonConverter。也许,这不是一个完美的解决方案,但它确实有效。

这是转换器:

public class NullConverter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.GetString();
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        if (value == "null_null") writer.WriteNullValue();
        else writer.WriteStringValue(value);
    }
}

你可以这样使用它:

var request = new ContactCreateRequest()
{
    Contact = new ContactEntity
    {
        LastName = "Jane",
        JobTitle = "null_null",   // initializing to a "null_null" string instead of null
        UpdateAction = "Update"
     }
};

Console.WriteLine(JsonSerializer.Serialize(request, new JsonSerializerOptions() { 
                        Converters = { new NullConverter()}, 
                        IgnoreNullValues = true})
                  );

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
相关资源
最近更新 更多