Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/NJsonSchema.Tests/Generation/AttributeGenerationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,20 @@ public void When_property_has_required_keyword_and_nullable_type_then_it_is_requ
Assert.True(schema.Properties["Name"].IsNullable(SchemaType.JsonSchema));
Assert.Null(schema.Properties["Name"].MinLength);
}

[Fact]
public void When_property_has_required_keyword_and_nullable_type_then_it_is_nullable_in_Swagger2()
{
// Act
var schema = NewtonsoftJsonSchemaGenerator.FromType<ClassWithRequiredNullableKeyword>(
new NewtonsoftJsonSchemaGeneratorSettings { SchemaType = SchemaType.Swagger2 });

// Assert: the required keyword forces the nullable property into Swagger2's required
// array, which by itself would signal "non-null". x-nullable must be emitted so the
// declared nullability is not silently lost.
Assert.Contains("Name", schema.RequiredProperties);
Assert.True(schema.Properties["Name"].IsNullable(SchemaType.Swagger2));
}
#endif

#if NET6_0_OR_GREATER
Expand Down
10 changes: 5 additions & 5 deletions src/NJsonSchema.Tests/Generation/DataContractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,19 @@ public void When_DataContractRequired_is_set_property_is_nullable_in_OpenApi3()
}

[Fact]
public void When_DataContractRequired_is_set_property_is_not_nullable_in_Swagger2()
public void When_DataContractRequired_is_set_property_is_nullable_in_Swagger2()
{
// Act
var schema = NewtonsoftJsonSchemaGenerator.FromType<Person>(new NewtonsoftJsonSchemaGeneratorSettings { SchemaType = SchemaType.Swagger2 });
var json = schema.ToJson();

// Assert
Assert.True(schema.ActualProperties["middleName"].IsRequired);
Assert.False(schema.ActualProperties["middleName"].IsNullable(SchemaType.Swagger2));
Assert.True(schema.ActualProperties["middleName"].IsNullable(SchemaType.Swagger2));

// not nullable, because Swagger2 does not know null but it has to set "required"
// because not setting the property would result in a serialization error,
// see When_DataContractRequired_is_set_then_undefined_is_not_allowed
// The property must be "required" because not setting it would result in a serialization
// error, but its value may still be null. Swagger2 has no native null, so x-nullable
// is emitted to express that the required value can be null.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ public void When_property_has_required_keyword_and_nullable_type_then_it_is_requ
Assert.Null(schema.Properties["Name"].MinLength);
}

[Fact]
public void When_property_has_required_keyword_and_nullable_type_then_it_is_nullable_in_Swagger2()
{
// Act
var schema = JsonSchema.FromType<ClassWithRequiredNullableKeyword>(
new SystemTextJsonSchemaGeneratorSettings { SchemaType = SchemaType.Swagger2 });

// Assert: the required keyword forces the nullable property into Swagger2's required
// array, which by itself would signal "non-null". x-nullable must be emitted so the
// declared nullability is not silently lost.
Assert.Contains("Name", schema.RequiredProperties);
Assert.True(schema.Properties["Name"].IsNullable(SchemaType.Swagger2));
}

public class ClassWithJsonRequired
{
[System.Text.Json.Serialization.JsonRequired]
Expand Down
12 changes: 10 additions & 2 deletions src/NJsonSchema/Generation/JsonSchemaGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,9 +1222,17 @@ public void AddProperty(
propertySchema.MinLength = 1;
}

if (!isNullable && Settings.SchemaType == SchemaType.Swagger2)
if (Settings.SchemaType == SchemaType.Swagger2)
{
if (!parentSchema.RequiredProperties.Contains(propertyName))
if (parentSchema.RequiredProperties.Contains(propertyName))
{
if (isNullable)
{
// Swagger2 has no native nullable
propertySchema.IsNullableRaw = true;
}
}
else if (!isNullable)
{
parentSchema.RequiredProperties.Add(propertyName);
}
Expand Down