system.text.json 在序列化时显式设置 null 属性,同时忽略未设置的属性

system.text.json explicitly set null attributes while ignoring unset attributes when serializing

我正在尝试将 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 应该显式设置为空。

编辑:由于 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})
                  );

原来有一个属性可以用来覆盖 JsonPropertyOption。 用带条件的 JsonIngore 属性装饰 JobTitle JsonIgnoreCondition.Never,这将覆盖 JsonSerializerOptions 中的 JsonIgnoreCondition,允许忽略 POCO 模型中的所有其他可为空的属性

     [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
    public string JobTitle { get; set; }

序列化 class

 var request = new ContactCreateRequest
{
   Contact = new ContactEntity
   {
      LastName = "Jane",
      JobTitle = null,
      UpdateAction = "Update"
   }
}
  var options = new JsonSerializerOptions{
     DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};

    var requestJson = JsonSerializer.Serialize(request, options);