OpenAPITools / OpenAPITools/openapi-generator

[BUG][csharp][csharp-netcore] JSON response deserialized as string, containing quotes

Open
#10,441 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When accessing an endpoint that returns a string with content-type application/json (quoted due to serialization), the string is deserialized as a raw string instead of JSON, leading to a response containing quotes that were not part of the original content.

A common example would be an endpoint that returns a JWT token as string with content-type application/json. Of course the API can be modified to return plain text in this case but for the sake of consistency it would be nice to return JSON in all endpoints. The client will currently receive the token string containing additional quotes from the server-side JSON serialization, leading to an invalid token string that first needs to be un-quoted before it can be used as a JWT token. This does not make sense as the content-type clearly states that the content is JSON and should be treated (deserialized) as such.

As far as I can see .NET client code generators for csharp and csharp-netcore are affected but there may be other generators and / or datatypes that have the same issue (see related Issues). In case this behavior is intended, I would like to know how to do it correctly without having to post-process the returned result.

openapi-generator version

I am using 5.2.0 and as far as I can tell this is not a regression, it has always been like this.

OpenAPI declaration file content or url
openapi: 3.0.2
info:
  title: MyAPI
  version: '1.0.0'
paths:
  /token:
    post:
      summary: Send login to the server to receive access-token
      responses:
        '200':
          description: OK. Login was successful. 
          content:
            application/json:
              schema:
                title: token
                type: string
        '401':
          description: Unauthorized. Login failed. 
      security:
        - UserAuth: []
components:
  securitySchemes:
    UserAuth: 
      type: http
      scheme: basic
Generation Details
java -jar openapi-generator-cli-5.2.0.jar generate -i openapi.yaml -g csharp-netcore -p targetFramework=net5.0
Steps to reproduce
  1. Generate any .NET client using openapi generator for an API that returns a string with content-type application/json, such as the example above.
  2. Have the server return a string foo encapsulated as JSON (so it will be serialized as "foo")
  3. Call the endpoint using the generated client and inspect the string returned to the client consumer

Expected result: foo
Actual result: "foo"

Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/9364

Suggest a fix

The generated ApiClient contains a Deserialize-method that treats all string types as raw string content regardless of the returned content-type.

See internal object Deserialize(IRestResponse response, Type type) in:

Or see the following snippet, taken from the csharp-netcore templates:

if (type == typeof(string) || type.Name.StartsWith("System.Nullable")) // return primitive type
{
    return Convert.ChangeType(response.Content, type); // << this is potentially wrong in case response.Content is valid JSON
}

// at this point, it must be a model (json)
try
{
    return JsonConvert.DeserializeObject(response.Content, type, _serializerSettings);
}

Possible remedy:
I suggest to pass all content that is declared as being application/json to JsonConvert.DeserializeObject (or create an error if the requested type is not deserializable from JSON).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Deserialize method in modules/openapi-generator/src/main/resources/csharp-netcore/ApiClient.mustache and csharp/ApiClient.mustache, then generate a csharp-netcore client using the supplied OpenAPI declaration and command. Reproduce the application/json string response and compare the returned value with the expected foo. Done means the generated clients handle the quoted JSON string without returning extra quotes.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.