Skip to content

Commit

Permalink
Merge pull request #582 from SteveDunn/581-stj-guid-exception
Browse files Browse the repository at this point in the history
The System.Text.JsonConverter now throws a JsonException
  • Loading branch information
SteveDunn authored Apr 30, 2024
2 parents 909f1db + 8b90b54 commit de506e6
Show file tree
Hide file tree
Showing 1,438 changed files with 13,985 additions and 4,287 deletions.
11 changes: 8 additions & 3 deletions src/Vogen/Templates/Guid/Guid_SystemTextJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ class VOTYPESystemTextJsonConverter : global::System.Text.Json.Serialization.Jso
{
public override VOTYPE Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
{
return VOTYPE.Deserialize(System.Guid.Parse(reader.GetString()));
return VOTYPE.Deserialize(reader.GetGuid());
}

public override void Write(System.Text.Json.Utf8JsonWriter writer, VOTYPE value, global::System.Text.Json.JsonSerializerOptions options)
{
writer.WriteStringValue(value.Value);
}

#if NET6_0_OR_GREATER
#if NET6_0_OR_GREATER // we can't call Read or use GetGuid from JsonReader as it expects a token type of string, but here we have have 'propertyname'.
public override VOTYPE ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options)
{
return VOTYPE.Deserialize(System.Guid.Parse(reader.GetString()));
if (global::System.Guid.TryParse(reader.GetString(), out global::System.Guid g))
{
return VOTYPE.Deserialize(g);
}

throw new global::System.Text.Json.JsonException("Unable to parse the GUID for an instance of VOTYPE");
}

public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, VOTYPE value, global::System.Text.Json.JsonSerializerOptions options)
Expand Down
34 changes: 34 additions & 0 deletions tests/ConsumerTests/BugFixTests/BugFix581.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Text.Json;

namespace ConsumerTests.BugFixTests.BugFix581;

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

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

/// <summary>
/// Fixes bug https://github.com/SteveDunn/Vogen/issues/581 where GUIDs that are deserialized
/// with null, throw a NullReferenceException instead of System.Text.JsonException.
/// </summary>
public class Tests
{
[Fact]
public void Should_throw_Stj_exception_with_null_passed()
{
Action a = () => JsonSerializer.Deserialize<ObjectContainerForVo>("""{"Ot":null}""");
a.Should().ThrowExactly<JsonException>().WithMessage("The JSON value could not be converted to ConsumerTests.BugFixTests.BugFix581.ObjectType. Path: $.Ot | LineNumber: 0 | BytePositionInLine: 10.");
}

[Fact]
public void Should_throw_Stj_exception_with_invalid_guid_passed()
{
Action a = () => JsonSerializer.Deserialize<ObjectContainerForVo>("""{"Ot":"Trevor woz ere"}""");
a.Should().ThrowExactly<JsonException>().WithMessage("The JSON value could not be converted to ConsumerTests.BugFixTests.BugFix581.ObjectType. Path: $.Ot | LineNumber: 0 | BytePositionInLine: 22.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Shared;
using VerifyXunit;
using Vogen;

namespace SnapshotTests.BugFixes;

// See https://github.com/SteveDunn/Vogen/issues/581
[UsesVerify]
public class Bug581_StjDeserializer_throws_correct_exception
{
// The System.Text.Json converter called Guid.Parse, which in turn threw a NullReferenceException.
// It should now use Guid.TryParse and return an STJ exception.
// This test just verifies that the correct code is generated. The consumer tests verify the runtime
// behaviour.
[Fact]
public async Task Test()
{
var source = """
using System;
using Vogen;
using System.Text.Json;
[ValueObject(typeof(Guid))]
public partial struct Vo
{
}
""";

await RunTest(source);
}


private static Task RunTest(string source) =>
new SnapshotRunner<ValueObjectGenerator>()
.WithSource(source)
.IgnoreInitialCompilationErrors()
.RunOnAllFrameworks();

}
Loading

0 comments on commit de506e6

Please sign in to comment.