From 932884ebd5efaba2ba035eaec96f62574b1b45d8 Mon Sep 17 00:00:00 2001 From: Twan Jacobs Date: Sat, 5 Feb 2022 16:32:17 +0100 Subject: [PATCH] Fix DateFormatConverter for System.Text.Json (#1490) --- .../GeneralGeneratorTests.cs | 99 +++++++++++++++++++ .../DateFormatConverterTemplateModel.cs | 5 +- .../Templates/DateFormatConverter.liquid | 12 ++- 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs b/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs index d1f938522..e2941c5d6 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs @@ -1461,6 +1461,39 @@ public async Task When_definition_contains_date_converter_should_be_added_for_da AssertCompile(code); } + [Fact] + public async Task When_definition_contains_date_and_use_system_text_json_then_converter_should_be_added_for_datetime() + { + //// Arrange + var json = +@"{ + ""type"": ""object"", + ""properties"": { + ""a"": { + ""type"": ""string"", + ""format"": ""date"" + } + } +}"; + var schema = await JsonSchema.FromJsonAsync(json); + + //// Act + var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings + { + ClassStyle = CSharpClassStyle.Poco, + SchemaType = SchemaType.Swagger2, + DateType = "System.DateTime", + JsonLibrary = CSharpJsonLibrary.SystemTextJson + }); + var code = generator.GenerateFile("MyClass"); + + //// Assert + Assert.Contains(@"class DateFormatConverter", code); + Assert.Contains(@"[System.Text.Json.Serialization.JsonConverter(typeof(DateFormatConverter))]", code); + + AssertCompile(code); + } + [Fact] public async Task When_no_typeNameHint_is_available_then_title_is_used_as_class_name() { @@ -1605,6 +1638,39 @@ public async Task When_definition_contains_date_converter_should_be_added_for_da AssertCompile(code); } + [Fact] + public async Task When_definition_contains_date_and_use_system_text_json_then_converter_should_be_added_for_datetimeoffset() + { + //// Arrange + var json = +@"{ + ""type"": ""object"", + ""properties"": { + ""a"": { + ""type"": ""string"", + ""format"": ""date"" + } + } +}"; + var schema = await JsonSchema.FromJsonAsync(json); + + //// Act + var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings + { + ClassStyle = CSharpClassStyle.Poco, + SchemaType = SchemaType.Swagger2, + DateType = "System.DateTimeOffset", + JsonLibrary = CSharpJsonLibrary.SystemTextJson + }); + var code = generator.GenerateFile("MyClass"); + + //// Assert + Assert.Contains(@"class DateFormatConverter", code); + Assert.Contains(@"[System.Text.Json.Serialization.JsonConverter(typeof(DateFormatConverter))]", code); + + AssertCompile(code); + } + [Fact] public async Task When_definition_contains_datetime_converter_should_not_be_added() { @@ -1637,6 +1703,39 @@ public async Task When_definition_contains_datetime_converter_should_not_be_adde AssertCompile(code); } + [Fact] + public async Task When_definition_contains_datetime_and_use_system_text_json_then_converter_should_not_be_added() + { + //// Arrange + var json = + @"{ + ""type"": ""object"", + ""properties"": { + ""a"": { + ""type"": ""string"", + ""format"": ""date-time"" + } + } +}"; + var schema = await JsonSchema.FromJsonAsync(json); + + //// Act + var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings + { + ClassStyle = CSharpClassStyle.Poco, + SchemaType = SchemaType.Swagger2, + DateType = "System.DateTime", + JsonLibrary = CSharpJsonLibrary.SystemTextJson + }); + var code = generator.GenerateFile("MyClass"); + + //// Assert + Assert.DoesNotContain(@"class DateFormatConverter", code); + Assert.DoesNotContain(@"[System.Text.Json.Serialization.JsonConverter(typeof(DateFormatConverter))]", code); + + AssertCompile(code); + } + [Fact] public async Task When_record_no_setter_in_class_and_constructor_provided() { diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/DateFormatConverterTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/DateFormatConverterTemplateModel.cs index 44cc3f782..967a7016d 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Models/DateFormatConverterTemplateModel.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/DateFormatConverterTemplateModel.cs @@ -20,8 +20,11 @@ public DateFormatConverterTemplateModel(CSharpGeneratorSettings settings) { _settings = settings; } - + /// Gets or sets a value indicating whether to generate the DateFormatConverter class. public bool GenerateDateFormatConverterClass => _settings.ExcludedTypeNames?.Contains("DateFormatConverter") != true; + + /// Gets a value indicating whether to use System.Text.Json + public bool UseSystemTextJson => _settings.JsonLibrary == CSharpJsonLibrary.SystemTextJson; } } diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Templates/DateFormatConverter.liquid b/src/NJsonSchema.CodeGeneration.CSharp/Templates/DateFormatConverter.liquid index 0ab640dc2..7d8dc0630 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Templates/DateFormatConverter.liquid +++ b/src/NJsonSchema.CodeGeneration.CSharp/Templates/DateFormatConverter.liquid @@ -1,13 +1,19 @@ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")] {%- if UseSystemTextJson -%} -internal class DateFormatConverter : JsonConverter +internal class DateFormatConverter : System.Text.Json.Serialization.JsonConverter { public override System.DateTime Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { - return DateTime.Parse(reader.GetString()); + var dateTime = reader.GetString(); + if (dateTime == null) + { + throw new JsonException("Unexpected JsonTokenType.Null"); + } + + return System.DateTime.Parse(dateTime); } - public override void Write(System.Text.Json.Utf8JsonReader writer, System.DateTime value, System.Text.Json.JsonSerializerOptions options) + public override void Write(System.Text.Json.Utf8JsonWriter writer, System.DateTime value, System.Text.Json.JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("yyyy-MM-dd")); }