3

Please note, this is for System.Text.Json and not Json.Net, so How to unit test a custom JsonConverter isn't a duplicate.

I like to unit test my custom JsonConverter:

using System.Text.Json;

public class DateTimeShortConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // support yyyy-MM-dd but also with times
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
    }

I need a Utf8JsonReader and I need to feed that one with a string.

I tried this:

byte[] bytes = Encoding.UTF8.GetBytes("2019-01-02");
var reader = new Utf8JsonReader(bytes.AsSpan());

Which seems to work, but gives a crash in the converter when doing reader.GetString():

System.InvalidOperationException : Cannot get the value of a token type 'None' as a string. at System.Text.Json.Utf8JsonReader.GetString()

The reader.GetString() should be correct, see Microsoft's example, so I think I feed the Utf8JsonReader wrong.

The reader.Position is readonly, so that isn't also an option. How could I feed the Utf8JsonReader correctly with a string?

Full test:

using System;
using System.Text;
using System.Text.Json;
Using Xunit;

[Fact]
public void ReadDateTimeTests()
{
    // Arrange
    var input = "2019-01-02";

    var dateTimeShortConverter = new DateTimeShortConverter();
    byte[] bytes = Encoding.UTF8.GetBytes(input);
    var reader = new Utf8JsonReader(bytes.AsSpan());

    Type typeToConvert = typeof(DateTime);
    JsonSerializerOptions options = new JsonSerializerOptions();

    var expected = new DateTime(2019, 01, 02);

    // Act
    var result = dateTimeShortConverter.Read(ref reader, typeToConvert, options);

    // Assert
    Assert.Equal(expected, result);
}

update: this also doesn't answer my question: Exception when testing custom JsonConverter. I tried also (from that answer) without luck:

byte[] bytes = Encoding.UTF8.GetBytes(input);
var reader = new Utf8JsonReader(bytes.AsSpan(), false, new JsonReaderState(new JsonReaderOptions()));

Update

"2019-01-02" isn't correct JSON in C#, but "\"2019-01-02\"" is and it still gives the same error.

Julian
  • 33,915
  • 22
  • 119
  • 174

1 Answers1

5

Found the problem,

First "2019-01-02" is valid JSON, but not 2019-01-02, so I needed an escape there.

After that, I need one read to read the quote of the string: reader.Read();

So this works:

using System;
using System.Text;
using System.Text.Json;
Using Xunit;

[Fact]
public void ReadDateTimeTests2()
{
    // Arrange
    var input = "\"2019-01-02\"";

    var dateTimeShortConverter = new DateTimeShortConverter();
    byte[] bytes = Encoding.UTF8.GetBytes(input);
    var reader = new Utf8JsonReader(bytes.AsSpan());
    reader.Read(); // Read the quote

    Type typeToConvert = typeof(DateTime);
    JsonSerializerOptions options = new JsonSerializerOptions();

    var expected = new DateTime(2019, 01, 02);

    // Act
    var result = dateTimeShortConverter.Read(ref reader, typeToConvert, options);

    // Assert
    Assert.Equal(expected, result);
}
Julian
  • 33,915
  • 22
  • 119
  • 174