AdditionalProperties JsonExtensionData repeated for subclasses in generated C# contracts
See original GitHub issueGiven:
{
"x-generator": "NSwag v13.4.2.0 (NJsonSchema v10.1.11.0 (Newtonsoft.Json v12.0.0.0))",
"openapi": "3.0.0",
"info": {
"title": "My Title",
"version": "1.0.0"
},
"paths": {
"/WeatherForecast": {
"get": {
"tags": [
"WeatherForecast"
],
"operationId": "GetCurrentWeatherForecast",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
}
},
"400": {
"$ref": "#/components/responses/400",
"description": ""
},
"401": {
"$ref": "#/components/responses/401",
"description": ""
},
"403": {
"$ref": "#/components/responses/403",
"description": ""
},
"404": {
"$ref": "#/components/responses/404",
"description": ""
},
"500": {
"$ref": "#/components/responses/500",
"description": ""
},
"503": {
"$ref": "#/components/responses/503",
"description": ""
}
}
},
"post": {
"tags": [
"WeatherForecast"
],
"operationId": "UploadWeatherForecast",
"requestBody": {
"x-name": "request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": ""
},
"400": {
"$ref": "#/components/responses/400",
"description": ""
},
"401": {
"$ref": "#/components/responses/401",
"description": ""
},
"403": {
"$ref": "#/components/responses/403",
"description": ""
},
"404": {
"$ref": "#/components/responses/404",
"description": ""
},
"500": {
"$ref": "#/components/responses/500",
"description": ""
},
"503": {
"$ref": "#/components/responses/503",
"description": ""
}
}
}
}
},
"components": {
"schemas": {
"WeatherForecast": {
"type": "object",
"description": "Represents a weather forecast for the given date.",
"properties": {
"date": {
"type": "string",
"description": "The time of the forecast.",
"format": "date-time"
},
"temperatureC": {
"type": "integer",
"description": "The temp in celsius.",
"format": "int32"
},
"temperatureF": {
"type": "integer",
"description": "The temp.",
"format": "int32"
},
"summary": {
"type": "string",
"description": "The description."
}
}
},
"ProblemDetails": {
"type": "object",
"properties": {
"type": {
"type": "string",
"format": "uri",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"type": "integer",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"format": "uri",
"nullable": true
}
}
},
"ValidationProblemDetails": {
"allOf": [
{
"$ref": "#/components/schemas/ProblemDetails"
},
{
"type": "object",
"properties": {
"errors": {
"type": "object",
"nullable": true,
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
]
}
},
"responses": {
"400": {
"description": "Bad Request",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"503": {
"description": "Service Unavailable",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
},
"parameters": {
"AuthorizationHeaderParameter": {
"name": "Authorization",
"in": "header",
"required": true,
"description": "The HTTP Authorization request header contains the credentials to authenticate a user agent with a server (From MDN).",
"schema": {
"type": "string",
"nullable": false
}
}
}
}
}
{
"runtime": "NetCore31",
"defaultVariables": null,
"documentGenerator": {
"aspNetCoreToOpenApi": {
"project": "NSwagTestHarness.csproj",
"msBuildProjectExtensionsPath": null,
"configuration": "$(Configuration)",
"targetFramework": null,
"noBuild": true,
"verbose": false,
"workingDirectory": null,
"requireParametersWithoutDefault": true,
"apiGroupNames": null,
"defaultPropertyNameHandling": "Default",
"defaultReferenceTypeNullHandling": "Null",
"defaultDictionaryValueReferenceTypeNullHandling": "NotNull",
"defaultResponseReferenceTypeNullHandling": "NotNull",
"defaultEnumHandling": "String",
"flattenInheritanceHierarchy": false,
"generateKnownTypes": true,
"generateEnumMappingDescription": false,
"generateXmlObjects": false,
"generateAbstractProperties": false,
"generateAbstractSchemas": true,
"ignoreObsoleteProperties": false,
"allowReferencesWithProperties": false,
"excludedTypeNames": [],
"serviceHost": null,
"serviceBasePath": null,
"serviceSchemes": [],
"infoTitle": "Transaction Service",
"infoDescription": null,
"infoVersion": null,
"documentTemplate": null,
"documentProcessorTypes": [],
"operationProcessorTypes": [],
"typeNameGeneratorType": null,
"schemaNameGeneratorType": null,
"contractResolverType": null,
"serializerSettingsType": null,
"useDocumentProvider": true,
"documentName": "v1",
"aspNetCoreEnvironment": "Development",
"createWebHostBuilderMethod": null,
"startupType": "NSwagTestHarness.Startup",
"allowNullableBodyParameters": false,
"output": "gen/test-v1.json",
"outputType": "OpenApi3",
"assemblyPaths": [],
"assemblyConfig": null,
"referencePaths": [],
"useNuGetCache": false
}
},
"codeGenerators": {
"openApiToCSharpClient": {
"clientBaseClass": "ApiClientBase",
"configurationClass": null,
"generateClientClasses": true,
"generateClientInterfaces": true,
"injectHttpClient": true,
"disposeHttpClient": false,
"protectedMethods": [],
"generateExceptionClasses": true,
"exceptionClass": "TestClientException",
"wrapDtoExceptions": true,
"useHttpClientCreationMethod": false,
"httpClientType": "System.Net.Http.HttpClient",
"useHttpRequestMessageCreationMethod": true,
"useBaseUrl": false,
"generateBaseUrlProperty": false,
"generateSyncMethods": false,
"exposeJsonSerializerSettings": false,
"clientClassAccessModifier": "public",
"typeAccessModifier": "public",
"generateContractsOutput": true,
"contractsNamespace": "NSwagTestHarness.Client",
"contractsOutputFilePath": "../NSwagTestHarness.Client/gen/Contracts.g.cs",
"parameterDateTimeFormat": "o",
"generateUpdateJsonSerializerSettingsMethod": true,
"serializeTypeInformation": false,
"queryNullValue": "",
"className": "NSwagTestHarnessClient",
"operationGenerationMode": "SingleClientFromOperationId",
"additionalNamespaceUsages": [],
"additionalContractNamespaceUsages": [],
"generateOptionalParameters": true,
"generateJsonMethods": false,
"enforceFlagEnums": false,
"parameterArrayType": "System.Collections.Generic.IEnumerable",
"parameterDictionaryType": "System.Collections.Generic.IDictionary",
"responseArrayType": "System.Collections.Generic.ICollection",
"responseDictionaryType": "System.Collections.Generic.IDictionary",
"wrapResponses": false,
"wrapResponseMethods": [],
"generateResponseClasses": false,
"responseClass": "NSwagTestHarnessResponse",
"namespace": "NSwagTestHarness.Client",
"requiredPropertiesMustBeDefined": true,
"dateType": "System.DateTime",
"jsonConverters": null,
"anyType": "object",
"dateTimeType": "System.DateTime",
"timeType": "System.TimeSpan",
"timeSpanType": "System.TimeSpan",
"arrayType": "System.Collections.Generic.ICollection",
"arrayInstanceType": "System.Collections.Generic.List",
"dictionaryType": "System.Collections.Generic.IDictionary",
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.Generic.List",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"classStyle": "Poco",
"generateDefaultValues": true,
"generateDataAnnotations": true,
"excludedTypeNames": [],
"excludedParameterNames": [
"Authorization",
"Accept-Language"
],
"handleReferences": false,
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
"jsonSerializerSettingsTransformationMethod": null,
"inlineNamedArrays": false,
"inlineNamedDictionaries": false,
"inlineNamedTuples": true,
"inlineNamedAny": false,
"generateDtoTypes": true,
"generateOptionalPropertiesAsNullable": false,
"templateDirectory": null,
"typeNameGeneratorType": null,
"propertyNameGeneratorType": null,
"enumNameGeneratorType": null,
"serviceHost": null,
"serviceSchemes": null,
"output": "../NSwagTestHarness.Client/gen/Client.g.cs"
}
}
}
The generated contracts for ProblemDetails
and ValidationProblemDetails
both generate AdditionalProperties
which could be a problem with the properties conflicting:
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.11.0 (Newtonsoft.Json v12.0.0.0)")]
public partial class ProblemDetails
{
[Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Uri Type { get; set; }
[Newtonsoft.Json.JsonProperty("title", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Title { get; set; }
[Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public int? Status { get; set; }
[Newtonsoft.Json.JsonProperty("detail", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Detail { get; set; }
[Newtonsoft.Json.JsonProperty("instance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Uri Instance { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
[Newtonsoft.Json.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties; }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.11.0 (Newtonsoft.Json v12.0.0.0)")]
public partial class ValidationProblemDetails : ProblemDetails
{
[Newtonsoft.Json.JsonProperty("errors", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Collections.Generic.IDictionary<string, System.Collections.Generic.ICollection<string>> Errors { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
[Newtonsoft.Json.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties; }
set { _additionalProperties = value; }
}
}
My guess is that the disabling of CS0108
is hiding the warning.
#pragma warning disable 108
Wouldn’t it make sense that NJsonSchema or NSwag see the inherited property/configuration for JsonExtensionData
and not generate it?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:7 (3 by maintainers)
Top Results From Across the Web
No results found
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
This is a serious bug i’d say.
I ran into this issue with problem details as wel. It seems to have been partially fixed in #https://github.com/RicoSuter/NJsonSchema/issues/1447 but that does not cover deeper inheritance layers
@RicoSuter I’m thinking of having a crack at fixing this, is there any specific branch i should start from?