Nswag: SwaggerToCSharpClientGenerator: support of JsonPatchDocument<T> (HttpPatch)

Created on 28 Mar 2018  路  7Comments  路  Source: RicoSuter/NSwag

Hello,

when having a HttpPatch rest api method with a Microsoft.AspNetCore.JsonPatch.JsonPatchDocument<T> as argument the csharp client generation creates a custom poco type like JsonPatchDocumentOfMyT .
Since JsonPatchDocument provides a fluent way to define the patch operations like for example patchDoc.Replace(o => o.StringProperty, "B"); the generated custom poco is not very helpful.

Is there a way to exclude generic types from poco generation (such that the Microsoft.AspNetCore.JsonPatch.JsonPatchDocument<T> is kept in the client method signature)? Or, where can I preferably control the generation/mapping of such action method parameters in using the NSwag.CodeGeneration.CSharp?

Best regards,
peter

wiki enhancement

All 7 comments

For that you need to

  • add a custom type mapper (TypeMappers) to map the JsonPatchDocument<> type to an any class (empty but still with a name) and then
  • in the code generator exclude this particular DTO class from being generated (ExcludedDtoTypes) and
  • add a using to the Microsoft.AspNetCore.JsonPatch namespace (AdditionalNamespaceUsages)

Thanks for your response. I do not get further with "type to an any class (empty but still with a name)". I always get a "Could not find the JSON path of a referenced schema: Manually referenced schemas must be added to the 'Definitions' of a parent schema.". This is my current approach:

class JsonPatchDocumentMapper : ITypeMapper
{
    public async Task GenerateSchemaAsync(JsonSchema4 schema, TypeMapperContext context)
    {
        // add the inner type to definitions
        var argument = context.Type.GenericTypeArguments[0];
        var argumentSchema = await context.JsonSchemaGenerator.GenerateAsync(argument,
            context.JsonSchemaResolver);
        schema.Definitions.Add(argument.Name, argumentSchema);
        // map JsonPatchDocument to any type
        schema.Reference = new JsonSchema4() { Title = "Foo" };
    }

    public Type MappedType { get; } = typeof(JsonPatchDocument<>);
    public bool UseReference { get; }
}

Any help would be appreciated.

Best regards,
peter

I think you can just use the ObjectTypeMapper and map it to an empty schema of type Object.

Hi @ptr1120 . It seems like we are having similar issues. Did you get anywhere with this?

This is my issue: https://github.com/RSuter/NSwag/issues/1410

The generator output the schema in such a way that the operations root is expected, whereas the request simply needs to be an array of operations. Have you found a way around that?

I am also struggling with this, trying to create a patch according from the example in MS docs with an empty WebApi .netCore 3.0 project.

My action is specified as:

        [HttpPatch]
        public WeatherForecast Patch([FromBody] 
            [JsonSchemaType(typeof(JsonPatchDocument<WeatherForecast>))]
            JsonPatchDocument<WeatherForecast> patchDoc)
        {

First, if I use default values for Api and the CSharpClientGenerator, I get same described in this issue (i.e. a type named JsonPatchDocumentOfWeatherForecast intead of JsonPatchDocument<WeatherForecast>).

If I instead use below to configure swagger generation:

            //add the Swagger services
            services.AddSwaggerDocument(settings =>
            {
                settings
                    .TypeMappers
                    .Add(new ObjectTypeMapper(typeof(JsonPatchDocument<WeatherForecast>), new JsonSchema
                    {
                        Type = JsonObjectType.Object,
                    }));
            });

I get a swagger json file like:

"operationId": "WeatherForecast_Patch",
        "consumes": [
          "application/json-patch+json",
          "application/json",
          "text/json",
          "application/*+json"
        ],
        "parameters": [
          {
            "name": "patchDoc",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/JsonPatchDocumentOfWeatherForecast"
            },
            "x-nullable": false
          }
//...
"JsonPatchDocumentOfWeatherForecast": {
      "type": "object",
      "additionalProperties": {}
    }

For the CSharpClientGenerator this generates below code.

        public System.Threading.Tasks.Task<WeatherForecast> PatchAsync(System.Collections.Generic.IDictionary<string, object> patchDoc)
        {
            return PatchAsync(patchDoc, System.Threading.CancellationToken.None);
        }
//...
    public partial class JsonPatchDocumentOfWeatherForecast : System.Collections.Generic.Dictionary<string, object>
    {

    }

Excluding type JsonPatchDocumentOfWeatherForecast in the generator does not help since then I only end up with the System.Collections.Generic.IDictionary<string, object> patchDoc parameter for the patch action.

Any more hints of how to proceed?
Thanks.

Can we please have an example of how this should work?

Was this page helpful?
0 / 5 - 0 ratings