Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The System.Text.Json serializer for Guid backed objects throws System.ArgumentNullException instead of System.Text.Json.JsonException when the property value is null #581

Closed
matthewvarley opened this issue Apr 30, 2024 · 1 comment · Fixed by #582
Assignees
Labels
bug Something isn't working

Comments

@matthewvarley
Copy link

matthewvarley commented Apr 30, 2024

Describe the bug

System.Text.Json expects custom converters to throw JsonException or NotSupportedException. With a Guid backed ValueObject, the generated converter will throw ArgumentNullException for when presented with a null value in the raw JSON. This happens because the generated code calls into Guid.Parse instead of Guid.TryParse and then handling the result.

// This is the generated code
public override ObjectType Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
{
     return ObjectType.Deserialize(System.Guid.Parse(reader.GetString()));
}

This is a problem because throwing an ArgumentNullException here will cause ASP.NET WebApi endpoints to generate a 500 response instead of a 400. A minimal repro to generate the ArgumentNullException is included in the steps to reproduce.

Steps to reproduce

using System.Text.Json;
using Vogen;

namespace MinimalRepro
{
    public class Program
    {
        public static void Main()
        {
            // Throws ArgumentNullException instead of JsonException
            JsonSerializer.Deserialize<ObjectContainer>("{\"Ot\":null}");
        }
    }

    public class ObjectContainer
    {
        public required ObjectType Ot { get; set; }
    }

    [ValueObject<Guid>(Conversions.Default)]
    public readonly partial struct ObjectType
    {
    }
}

Expected behaviour

The expectation is for a System.Text.Json.Serialization.JsonConverter to throw System.Text.Json.JsonException. Manually changing the generated read method to something like this generates the expected behavior and triggers ASP.NET to return a 400.

public override ObjectType Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
{
  if (System.Guid.TryParse(reader.GetString(), out Guid g))
  {
    return ObjectType.Deserialize(g);
  }
  else
  {
    throw new System.Text.Json.JsonException("Unable to parse");
  }
}
@SteveDunn
Copy link
Owner

Thanks very much for the feedback and repro. This has now been fixed - good spot!
It will be in the next release, which is being built and should be available in an hour or so (once all the snapshot tests are finished! 🥱 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants