Skip to content

Do not mark require property as read only #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 10, 2018
Merged
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
61 changes: 54 additions & 7 deletions src/Microsoft.OpenApi/Models/OpenApiSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,32 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer)
/// Serialize <see cref="OpenApiSchema"/> to Open Api v2.0
/// </summary>
public void SerializeAsV2(IOpenApiWriter writer)
{
SerializeAsV2(writer: writer, parentRequiredProperties: new List<string>(), propertyName: null);
}

/// <summary>
/// Serialize to OpenAPI V2 document without using reference.
/// </summary>
public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
{
SerializeAsV2WithoutReference(
writer: writer,
parentRequiredProperties: new List<string>(),
propertyName: null);
}

/// <summary>
/// Serialize <see cref="OpenApiSchema"/> to Open Api v2.0 and handles not marking the provided property
/// as readonly if its included in the provided list of required properties of parent schema.
/// </summary>
/// <param name="writer">The open api writer.</param>
/// <param name="parentRequiredProperties">The list of required properties in parent schema.</param>
/// <param name="propertyName">The property name that will be serialized.</param>
internal void SerializeAsV2(
IOpenApiWriter writer,
IList<string> parentRequiredProperties,
string propertyName)
{
if (writer == null)
{
Expand All @@ -386,16 +412,28 @@ public void SerializeAsV2(IOpenApiWriter writer)
return;
}

SerializeAsV2WithoutReference(writer);
if (parentRequiredProperties == null)
{
parentRequiredProperties = new List<string>();
}

SerializeAsV2WithoutReference(writer, parentRequiredProperties, propertyName);
}

/// <summary>
/// Serialize to OpenAPI V2 document without using reference.
/// Serialize to OpenAPI V2 document without using reference and handles not marking the provided property
/// as readonly if its included in the provided list of required properties of parent schema.
/// </summary>
public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
/// <param name="writer">The open api writer.</param>
/// <param name="parentRequiredProperties">The list of required properties in parent schema.</param>
/// <param name="propertyName">The property name that will be serialized.</param>
internal void SerializeAsV2WithoutReference(
IOpenApiWriter writer,
IList<string> parentRequiredProperties,
string propertyName)
{
writer.WriteStartObject();
WriteAsSchemaProperties(writer);
WriteAsSchemaProperties(writer, parentRequiredProperties, propertyName);
writer.WriteEndObject();
}

Expand Down Expand Up @@ -463,7 +501,10 @@ internal void WriteAsItemsProperties(IOpenApiWriter writer)
writer.WriteExtensions(Extensions);
}

internal void WriteAsSchemaProperties(IOpenApiWriter writer)
internal void WriteAsSchemaProperties(
IOpenApiWriter writer,
IList<string> parentRequiredProperties,
string propertyName)
{
if (writer == null)
{
Expand Down Expand Up @@ -537,7 +578,8 @@ internal void WriteAsSchemaProperties(IOpenApiWriter writer)
writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, (w, s) => s.SerializeAsV2(w));

// properties
writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, s) => s.SerializeAsV2(w));
writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, key, s) =>
s.SerializeAsV2(w, Required, key));

// additionalProperties
writer.WriteOptionalObject(
Expand All @@ -549,7 +591,12 @@ internal void WriteAsSchemaProperties(IOpenApiWriter writer)
writer.WriteProperty(OpenApiConstants.Discriminator, Discriminator?.PropertyName);

// readOnly
writer.WriteProperty(OpenApiConstants.ReadOnly, ReadOnly, false);
// In V2 schema if a property is part of required properties of parent schema,
// it cannot be marked as readonly.
if (!parentRequiredProperties.Contains(propertyName))
{
writer.WriteProperty(name: OpenApiConstants.ReadOnly, value: ReadOnly, defaultValue: false);
}

// xml
writer.WriteOptionalObject(OpenApiConstants.Xml, Xml, (w, s) => s.SerializeAsV2(w));
Expand Down
113 changes: 113 additions & 0 deletions test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,60 @@ public class OpenApiSchemaTests
}
};

public static OpenApiSchema AdvancedSchemaWithRequiredPropertiesObject = new OpenApiSchema
{
Title = "title1",
Required = new List<string>(){ "property1" },
Properties = new Dictionary<string, OpenApiSchema>
{
["property1"] = new OpenApiSchema
{
Required = new List<string>() { "property3" },
Properties = new Dictionary<string, OpenApiSchema>
{
["property2"] = new OpenApiSchema
{
Type = "integer"
},
["property3"] = new OpenApiSchema
{
Type = "string",
MaxLength = 15,
ReadOnly = true
}
},
ReadOnly = true,
},
["property4"] = new OpenApiSchema
{
Properties = new Dictionary<string, OpenApiSchema>
{
["property5"] = new OpenApiSchema
{
Properties = new Dictionary<string, OpenApiSchema>
{
["property6"] = new OpenApiSchema
{
Type = "boolean"
}
}
},
["property7"] = new OpenApiSchema
{
Type = "string",
MinLength = 2
}
},
ReadOnly = true,
},
},
Nullable = true,
ExternalDocs = new OpenApiExternalDocs
{
Url = new Uri("http://example.com/externalDocs")
}
};

private readonly ITestOutputHelper _output;

public OpenApiSchemaTests(ITestOutputHelper output)
Expand Down Expand Up @@ -363,5 +417,64 @@ public void SerializeReferencedSchemaAsV3JsonWorks()
expected = expected.MakeLineBreaksEnvironmentNeutral();
actual.Should().Be(expected);
}

[Fact]
public void SerializeSchemaWRequiredPropertiesAsV2JsonWorks()
{
// Arrange
var outputStringWriter = new StringWriter();
var writer = new OpenApiJsonWriter(outputStringWriter);
var expected = @"{
""title"": ""title1"",
""required"": [
""property1""
],
""properties"": {
""property1"": {
""required"": [
""property3""
],
""properties"": {
""property2"": {
""type"": ""integer""
},
""property3"": {
""maxLength"": 15,
""type"": ""string""
}
}
},
""property4"": {
""properties"": {
""property5"": {
""properties"": {
""property6"": {
""type"": ""boolean""
}
}
},
""property7"": {
""minLength"": 2,
""type"": ""string""
}
},
""readOnly"": true
}
},
""externalDocs"": {
""url"": ""http://example.com/externalDocs""
}
}";

// Act
AdvancedSchemaWithRequiredPropertiesObject.SerializeAsV2(writer);
writer.Flush();
var actual = outputStringWriter.GetStringBuilder().ToString();

// Assert
actual = actual.MakeLineBreaksEnvironmentNeutral();
expected = expected.MakeLineBreaksEnvironmentNeutral();
actual.Should().Be(expected);
}
}
}