5

When I use Postman to test my API with a PUT request, I get this error:

"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-fe50a5f13435f11ef5d27de5f91d3c45-47c1ee82a70305a9-00",
"errors": {
    "$.extractionDate": [
        "The JSON value could not be converted to System.Nullable`1[System.DateTime]. Path: $.extractionDate | LineNumber: 0 | BytePositionInLine: 704."
    ]
}

I can see that an empty string that looks like this is being passed to the API:

"extractionDate":""

In my model, I have the ExtractionDate property set as nullable like this:

public DateTime? ExtractionDate { get; set; }

Due to things beyond my control, the old system that is using this API can't pass nulls, it can only pass a blank string for any values that are null.

Is there something else I need to do in order for the JSON to be valid?

Thanks!

5
  • why not send "extractionDate":null when having nothing to send? To help you, is important know if you are using Newtonsoft or System.Text.Json or the version of your ASP.NET if is Core or not. Commented Apr 28, 2022 at 20:27
  • So, you have control of the API and the deserialization of the json, but you don't have control of the client or what is actually being sent? Are you using Newtonsoft.Json? Commented Apr 28, 2022 at 20:31
  • is it what yoy are looking for stackoverflow.com/a/71926651/17239546 ? Commented Apr 28, 2022 at 20:35
  • @GeanRibeiro I am using System.Text.Json in a .Net 6 project. Thanks! Commented Apr 29, 2022 at 11:51
  • @JoshuaRobinson I am using System.Text.Json thanks! Commented Apr 29, 2022 at 11:52

2 Answers 2

12

Well, assuming that you have control of the API and the models on that end, you could write a custom JsonConverter<DateTime?> that handles empty strings by returning null.

A simple implementation of the JsonConverter<DateTime?> might look something like this...

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class NullableDateTimeConverter : JsonConverter<DateTime?>
{
    public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var @string = reader.GetString();
        if (string.IsNullOrWhiteSpace(@string))
        {
            return null;
        }
        return DateTime.Parse(@string);
    }

    public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
    {
        if (value != null)
        {
            writer.WriteStringValue(value.Value.ToString("o"));
        }
    }
}

Then, you can tell your model to use it with a JsonConverterAttribute.

using System;
using System.Test.Json.Serialization;

public class TheModel
{
    [JsonConverter(typeof(NullableDateTimeConverter))]
    public DateTime? ExtractionDate { get; set; }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Oh thank you, wow that looks very powerful tool! Could you make that something like generics? For example pass in a type, like DateTime, or Guid, or String, etc? Would that just be changing this part? JsonConverter<DateTime?>?
Good question. I'm afraid I'm not sure. You could maybe do some runtime type checking on typeToConvert in Read or value in Write to figure out how to serialize or deserailize? I don't know enough about System.Text.Json to say for sure if there is a better way. Sorry.
3

You can make an extension method and use it everywhere

    public static DateTime? ParseDateOrDefault(this string date)
    {

        if (string.IsNullOrEmpty(date))
            return null;

        return DateTime.Parse(date);
    }

Then in your api make another public string DateTime variable that will accept the datetime passed in. Make your current DateTime variable internal with getters and setters that have logic with the new extension method.

internal DateTime? MyDate 
{
  get
  {
    return MyDateStringVariable.ParseDateOrDefault();
  }
  ...
}

3 Comments

Would that internal DateTime? MyDate go in my models? Like would I replace public DateTime? ExtractionDate { get; set; } with that? Thanks!
Hi, I'm not quite sure how to use this extension. I made a static class called EmptyToNull in an Extensions folder and put your ParseDateOrDefault method in there. In my model, I made sure to add a using directive for the Extensions folder. I then turned this: public DateTime? ExtractionDate { get; set; } into this: public DateTime? ExtractionDate { get { return ExtractionDate.ParseDateOrDefault(); } but it can't find the ParseDateOrDefault() extension method
Sorry for the late reply. Yes it would go in your api model. If the solution below didn't work please post your code. It may be the access modifiers preventing you from calling it.

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.