diff --git a/README.md b/README.md index 5228b00..029892f 100644 --- a/README.md +++ b/README.md @@ -30,5 +30,17 @@ app.UseExceptionHandler(); * https://medium.com/@niteshsinghal85/multiple-request-response-examples-for-swagger-ui-in-asp-net-core-864c0bdc6619 ## Request Body에서 null을 명시할 경우 무시할 수 없음 -* JsonIgnoreCondition은 현재 null 쓰기무시만 있고 null 읽기무시는 없음 -* https://github.com/dotnet/runtime/issues/66490#issuecomment-1142804662 +* `JsonIgnoreCondition.WhenReadingNull`이 추가될 예정도 없음 +* https://stackoverflow.com/questions/77516935/ignore-json-null-value-in-system-text-json-deserialize + +```csharp +builder.Services.ConfigureHttpJsonOptions(options => { + options.SerializerOptions.WriteIndented = true; + options.SerializerOptions.IncludeFields = true; + options.SerializerOptions.PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate; + options.SerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver + { + Modifiers = { InterceptNullSetter } + }; +}); +``` diff --git a/src/WebApplicationMinimalApi8/Dto/MessageDto.cs b/src/WebApplicationMinimalApi8/Dto/MessageDto.cs index e2bcbd2..9d38436 100644 --- a/src/WebApplicationMinimalApi8/Dto/MessageDto.cs +++ b/src/WebApplicationMinimalApi8/Dto/MessageDto.cs @@ -6,7 +6,8 @@ namespace WebApplicationMinimalApi8.Dto; public record MessageDto { - public string Body { get; init; } = "안녕하신지"; + public string NullString { get; init; } = "기본값"; + public IEnumerable NullStrings { get; init; } = []; } @@ -14,15 +15,22 @@ public class MessageDtoValidator : AbstractValidator { public MessageDtoValidator() { - RuleFor(x => x.Body).NotEmpty().NotNull(); + RuleFor(x => x.NullString).NotEmpty(); } } +#pragma warning disable CS8625 + public class MessageDtoExmaple : IMultipleExamplesProvider { public IEnumerable> GetExamples() { - yield return SwaggerExample.Create("빈값", new MessageDto { Body = "" }); - yield return SwaggerExample.Create("null", new MessageDto { Body = null }); + yield return SwaggerExample.Create("null", new MessageDto + { + NullString = null, + NullStrings = null + }); + yield return SwaggerExample.Create("notnull", new MessageDto { NullString = "값", NullStrings = ["값"] }); + yield return SwaggerExample.Create("error", new MessageDto { NullString = "" }); } } diff --git a/src/WebApplicationMinimalApi8/Program.cs b/src/WebApplicationMinimalApi8/Program.cs index 6a23e5c..52df7f4 100644 --- a/src/WebApplicationMinimalApi8/Program.cs +++ b/src/WebApplicationMinimalApi8/Program.cs @@ -1,10 +1,13 @@ using System.Reflection.Metadata.Ecma335; +using System.Text.Json.Serialization.Metadata; +using System.Text.Json.Serialization; using FluentValidation; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.Filters; using WebApplicationMinimalApi8.Dto; using WebApplicationMinimalApi8.EndpointFilters; using WebApplicationMinimalApi8.ExceptionHandlers; +using System.Linq; var builder = WebApplication.CreateBuilder(args); @@ -16,6 +19,15 @@ builder.Services.AddSwaggerExamplesFromAssemblyOf(); builder.Services.AddValidatorsFromAssemblyContaining(); builder.AddFluentValidationEndpointFilter(); +builder.Services.ConfigureHttpJsonOptions(options => { + options.SerializerOptions.WriteIndented = true; + options.SerializerOptions.IncludeFields = true; + options.SerializerOptions.PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate; + options.SerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver + { + Modifiers = { InterceptNullSetter } + }; +}); if (builder.Environment.IsEnvironment("Best")) { @@ -49,3 +61,19 @@ app.Run(); +static void InterceptNullSetter(JsonTypeInfo typeInfo) +{ + foreach (var (propertyInfo, setProperty) in from propertyInfo in typeInfo.Properties + let setProperty = propertyInfo.Set + where setProperty is not null + select (propertyInfo, setProperty)) + { + propertyInfo.Set = (obj, value) => + { + if (value != null) + { + setProperty(obj, value); + } + }; + } +}