0

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.

5
  • Is this a PATCH REST request? Commented Jul 9, 2020 at 20:02
  • PUT sadly I am working with an external api the behaves strangly. Commented Jul 9, 2020 at 20:07
  • Can you provide an example POCO? It would help make an answer more directly relevant. Commented Jul 9, 2020 at 20:17
  • So to send an update that changes the Department to "Marketing", sets Title to null, and affects nothing else, you would send {"contact":{"Department":"Marketing","Title":null}}... is that correct? Commented Jul 9, 2020 at 20:29
  • @madreflection yes that is how the API works Commented Jul 9, 2020 at 20:33

2 Answers 2

2

Turns out there is an attribute you can use to override the JsonPropertyOption. Decorate JobTitle with JsonIngore attribute with Contition JsonIgnoreCondition.Never, this will override JsonIgnoreCondition in JsonSerializerOptions, allowing all other nullable properties in your POCO model to be ignored

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

When serializeing the 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);
Sign up to request clarification or add additional context in comments.

Comments

0

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})
                  );

2 Comments

Thank you. This is the approach I took. Not elegant but did do the job.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.