I am trying to serializing a POCO object into an update request.
My unset values are serialized as null, which causes them to be updated to null.
If I set IgnoreNullValues to true this fixes the problem. However, then there is no way to explicitly update an attribute to null.
I am thinking that the approach to solving this problem is to create a custom null object that serializes to null and ignore the real null values. Is this possible? How else can I solve this problem?
Edit: Added example of POCO request object I am trying to serialize
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; }
}
I would like the following
var request = new ContactCreateRequest
{
Contact = new ContactEntity
{
LastName = "Jane",
JobTitle = null,
UpdateAction = "Update"
}
}
{"contact": {"LastName": "Jane", "JobTitle": null, "UpdateAction": "Update"}}
... but of course this will not work because all the unset fields are also null so they treated the same as JobTitle. That is why I am wondering if I need to use a null object pattern to define that JobTitle should be set null explicitly.
EDIT: Due to very a very appropriate comment of dbc, I've changed the "null" value to "null_null" to avoid problems with processing the "Null" last names.
You can achieve your goal by creating a custom JSON converter, assigning a "null" "null_null"
value to your string properties instead of null
and using IgnoreNullValues
option. The JSON serializer will ignore all the not initialized values and the custom converter will serialize your "null" "null_null"
value as if it was null
. If you want similar functionality for other types e.g. your DateTime, then you need to add a new DateTime JsonConverter or create a JsonConverter which is more generic and can handle all the possible cases. Maybe, it's not a perfect solution but it works.
Here is the converter:
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);
}
}
You can use it like this:
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})
);