generated from easy-template/csharp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b13c0c9
commit fbb6f20
Showing
5 changed files
with
305 additions
and
33 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
src/SystemTextJsonNullTests/SystemTextJsonNullTests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="xunit" Version="2.5.3" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="Xunit" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
using System.Reflection; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using System.Text.Json.Serialization.Metadata; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace SystemTextJsonNullTests; | ||
|
||
public class UnitTest1 | ||
{ | ||
|
||
|
||
|
||
|
||
public static JsonSerializerOptions JsonSerializerOptions { get; } = new() | ||
{ | ||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||
PropertyNameCaseInsensitive = true, | ||
WriteIndented = false, | ||
PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate, | ||
TypeInfoResolver = new DefaultJsonTypeInfoResolver | ||
{ | ||
Modifiers = { InterceptNullSetter, } | ||
} | ||
}; | ||
|
||
static void InterceptNullSetter(JsonTypeInfo typeInfo) | ||
{ | ||
static bool IsRequiredMember(JsonPropertyInfo propertyInfo) => | ||
propertyInfo.AttributeProvider?.GetCustomAttributes(typeof(System.Runtime.CompilerServices.RequiredMemberAttribute), true).Any() ?? false; | ||
|
||
|
||
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 is null) | ||
{ | ||
if (IsRequiredMember(propertyInfo)) | ||
{ | ||
throw new JsonException($"Null value not allowed for '{propertyInfo.Name}'"); | ||
} | ||
|
||
NullabilityInfoContext context = new(); | ||
|
||
var nullabilityInfo = propertyInfo.AttributeProvider switch | ||
{ | ||
FieldInfo fieldInfo => context.Create(fieldInfo), | ||
PropertyInfo propertyInfo => context.Create(propertyInfo), | ||
_ => null | ||
}; | ||
|
||
if (nullabilityInfo?.WriteState is NullabilityState.Nullable) | ||
{ | ||
setProperty(obj, value); | ||
} | ||
} | ||
else | ||
{ | ||
setProperty(obj, value); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
[Fact] | ||
public void RequireValueNull() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": null | ||
} | ||
"""; | ||
|
||
var exception = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions)); | ||
|
||
Assert.Equal("Null value not allowed for 'requireValue'", exception.Message); | ||
} | ||
|
||
[Fact] | ||
public void RequireValueNull2() | ||
{ | ||
var json = "{}"; | ||
|
||
var exception = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions)); | ||
|
||
Assert.Equal("JSON deserialization for type 'SystemTextJsonNullTests.Dto' was missing required properties, including the following: requireValue", exception.Message); | ||
} | ||
|
||
[Fact] | ||
public void NotNullDefaultValueNull() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"NotNullDefaultValue": null | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.NotNullDefaultValue, ""); | ||
} | ||
|
||
[Fact] | ||
public void NotNullDefaultValueNull2() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.NotNullDefaultValue, ""); | ||
} | ||
|
||
[Fact] | ||
public void NullableDefaultValueExpectDefault() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal("", sut.NullableDefaultValue); | ||
} | ||
|
||
[Fact] | ||
public void NullableDefaultValueExpectNull() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"NullableDefaultValue": null | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.NullableDefaultValue, null); | ||
} | ||
|
||
[Fact] | ||
public void NullableDefaultValueExpectAAA() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"NullableDefaultValue": "AAA" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal("", sut.RequireValue); | ||
Assert.Equal("AAA", sut.NullableDefaultValue); | ||
} | ||
|
||
[Fact] | ||
public void NullableValueExpectDefault() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.NullableValue, null); | ||
} | ||
|
||
[Fact] | ||
public void NullableValueExpectNull() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"NullableValue": null | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.NullableValue, null); | ||
} | ||
|
||
[Fact] | ||
public void NullableValueExpectCCC() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"NullableValue": "CCC" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal("", sut.RequireValue); | ||
Assert.Equal(sut.NullableValue, "CCC"); | ||
} | ||
|
||
|
||
[Fact] | ||
public void StringValuesExpectDefault() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "" | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.StringValues, []); | ||
} | ||
|
||
[Fact] | ||
public void StringValuesExpectNull() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"StringValues": null | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal(sut.RequireValue, ""); | ||
Assert.Equal(sut.StringValues, []); | ||
} | ||
|
||
[Fact] | ||
public void StringValuesExpectCCC() | ||
{ | ||
var json = """ | ||
{ | ||
"RequireValue": "", | ||
"StringValues": ["CCC"] | ||
} | ||
"""; | ||
|
||
var sut = JsonSerializer.Deserialize<Dto>(json, JsonSerializerOptions); | ||
|
||
Assert.Equal("", sut.RequireValue); | ||
Assert.Equal(sut.StringValues, ["CCC"]); | ||
} | ||
} | ||
|
||
|
||
public record Dto | ||
{ | ||
public required string RequireValue { get; init; } | ||
public string NotNullDefaultValue { get; init; } = ""; | ||
public string? NullableDefaultValue { get; init; } = ""; | ||
public string? NullableValue { get; init; } | ||
public IEnumerable<string> StringValues { get; init; } = []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.