OpenAPITools / OpenAPITools/openapi-generator
[BUG][csharp][csharp-netcore] JSON response deserialized as string, containing quotes
Nobody has claimed this yet.
- 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
- Generate any .NET client using openapi generator for an API that returns a string with content-type application/json, such as the example above.
- Have the server return a string
fooencapsulated as JSON (so it will be serialized as"foo") - 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:
- https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/csharp-netcore/ApiClient.mustache
- https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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