diff --git a/specs/Qowaiv.Specs/Identifiers/ID_Cast_specs.cs b/specs/Qowaiv.Specs/Identifiers/ID_Cast_specs.cs index 554090e01..d9e019229 100644 --- a/specs/Qowaiv.Specs/Identifiers/ID_Cast_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/ID_Cast_specs.cs @@ -84,10 +84,5 @@ public void non_GUID_string_to_GUID() public void long_to_GUID() => ((object)123546L).Invoking(id => (CustomGuid)id) .Should().Throw(); - - [Test] - public void invalid_JSON_input() - => (-1L).Invoking(Int64Id.FromJson) - .Should().Throw(); } diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs index b03b7ac65..8e219e3d0 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Int32_specs.cs @@ -49,6 +49,37 @@ public void System_Text_JSON_deserialization(object json, Int32Id svo) [TestCase("12345678", 12345678L)] public void System_Text_JSON_serialization(Int32Id svo, object json) => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [TestCase(-2)] + [TestCase(17)] + [TestCase("17")] + [TestCase(int.MaxValue + 1L)] + public void taking_constrains_into_account(object json) + { + json.Invoking(JsonTester.Read_System_Text_JSON>) + .Should().Throw() + .WithMessage("Not a valid identifier."); + } + + private sealed class ForEven : Int32IdBehavior + { + public override bool TryCreate(object? obj, out object? id) + { + if(obj is int even && even % 2 == 0) + { + id = even; + return true; + } + { + id = null; + return false; + } + } + + public override bool TryParse(string? str, out object? id) + => TryCreate(int.TryParse(str, out int even) ? even : null, out id); + } + #endif [TestCase("", "")] [TestCase(12345678L, 12345678)] @@ -60,13 +91,6 @@ public void convention_based_deserialization(object json, Int32Id svo) [TestCase("12345678", 12345678L)] public void convention_based_serialization(Int32Id svo, object json) => JsonTester.Write(svo).Should().Be(json); - - [TestCase("Invalid input", typeof(FormatException))] - [TestCase(long.MaxValue, typeof(InvalidCastException))] - public void throws_for_invalid_json(object json, Type exceptionType) - => json.Invoking(JsonTester.Read) - .Should().Throw() - .Which.Should().BeOfType(exceptionType); } public class Supports_type_conversion diff --git a/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs b/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs index 3c63a7fb0..a0b8fdfac 100644 --- a/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs +++ b/specs/Qowaiv.Specs/Identifiers/Id_for_Int64_specs.cs @@ -48,7 +48,37 @@ public void System_Text_JSON_deserialization(object json, Int64Id svo) [TestCase(123456789L, "123456789")] public void System_Text_JSON_serialization(Int64Id svo, object json) => JsonTester.Write_System_Text_JSON(svo).Should().Be(json); + + [TestCase(-2)] + [TestCase(17)] + [TestCase("17")] + public void taking_constrains_into_account(object json) + { + json.Invoking(JsonTester.Read_System_Text_JSON>) + .Should().Throw() + .WithMessage("Not a valid identifier."); + } + + private sealed class ForEven : Int64IdBehavior + { + public override bool TryCreate(object? obj, out object? id) + { + if (obj is long even && even % 2 == 0) + { + id = even; + return true; + } + { + id = null; + return false; + } + } + + public override bool TryParse(string? str, out object? id) + => TryCreate(long.TryParse(str, out long even) ? even : null, out id); + } #endif + [TestCase("", null)] [TestCase(123456789L, 123456789L)] [TestCase("123456789", 123456789L)] diff --git a/src/Qowaiv/Identifiers/Int32IdBehavior.cs b/src/Qowaiv/Identifiers/Int32IdBehavior.cs index f60f78b56..7dac52c4a 100644 --- a/src/Qowaiv/Identifiers/Int32IdBehavior.cs +++ b/src/Qowaiv/Identifiers/Int32IdBehavior.cs @@ -37,18 +37,12 @@ public override byte[] ToByteArray(object? obj) /// [Pure] - public override object? FromJson(long obj) + public override object? FromJson(long obj) => obj switch { - if (obj == 0) - { - return null; - } - else if (obj > 0 && obj <= int.MaxValue) - { - return (int)obj; - } - else throw Exceptions.InvalidCast(typeof(int), typeof(Id<>).MakeGenericType(GetType())); - } + 0 => null, + _ when obj > 0 && obj <= int.MaxValue && TryCreate(obj, out var created) && created is int id => id, + _ => throw Unparsable.ForValue(obj.ToString(), "Not a valid identifier.", typeof(Id<>).MakeGenericType(GetType())), + }; /// [Pure] diff --git a/src/Qowaiv/Identifiers/Int64IdBehavior.cs b/src/Qowaiv/Identifiers/Int64IdBehavior.cs index 62d859dd2..30257a4a6 100644 --- a/src/Qowaiv/Identifiers/Int64IdBehavior.cs +++ b/src/Qowaiv/Identifiers/Int64IdBehavior.cs @@ -39,12 +39,12 @@ public override string ToString(object? obj, string? format, IFormatProvider? fo /// [Pure] - public sealed override object? FromJson(long obj) + public sealed override object? FromJson(long obj) => obj switch { - if (obj == 0) return null; - else if (obj > 0) return obj; - else throw Exceptions.InvalidCast(typeof(long), typeof(Id<>).MakeGenericType(GetType())); - } + 0 => null, + _ when obj > 0 && TryCreate(obj, out var created) && created is long id => id, + _ => throw Unparsable.ForValue(obj.ToString(), "Not a valid identifier.", typeof(Id<>).MakeGenericType(GetType())), + }; /// [Pure] diff --git a/src/Qowaiv/Json/Identifiers/IdJsonConverter.cs b/src/Qowaiv/Json/Identifiers/IdJsonConverter.cs index 9d8ea8dbc..1fd5e5cfd 100644 --- a/src/Qowaiv/Json/Identifiers/IdJsonConverter.cs +++ b/src/Qowaiv/Json/Identifiers/IdJsonConverter.cs @@ -48,8 +48,12 @@ JsonTokenType.True or } catch (Exception x) { - if (x is JsonException) throw; - else throw new JsonException(x.Message, x); + var inner = x; + while (inner is TargetInvocationException && inner.InnerException is { }) + { + inner = inner.InnerException; + } + throw new JsonException(inner.Message, inner); } } @@ -77,17 +81,13 @@ public override void Write(Utf8JsonWriter writer, Id value, JsonSeria } } -#if NET6_0_OR_GREATER - /// - public override Id ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +- public override Id ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Id.FromJson(reader.GetString()); /// public override void WriteAsPropertyName(Utf8JsonWriter writer, Id value, JsonSerializerOptions options) => writer.WritePropertyName(value.ToJson()?.ToString() ?? string.Empty); - -#endif } [Pure]