Nswag: C# client throwing exception trying to Deserialize a json response into a string

Created on 19 Dec 2017  路  13Comments  路  Source: RicoSuter/NSwag

I am using an externally generated swagger.json definition that returns json data as a string. The client is failing with an exception calling DeserializeObject in the following code

 if (status_ == "200")
                        {
                            var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            var result_ = default(string);
                            try
                            {
                                result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(responseData_, _settings.Value);
                                return result_;
                            }
                            catch (System.Exception exception_)
                            {
                                throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception_);
                            }
                        }

The call to DeserializeObject fails (and is not required) when the result is also a string. The result should just be set to the reponseData value.

Whats the best way to accomplish this? Do I need to update templates?

Thanks.

question

Most helpful comment

A string like foobar is not valid JSON, only "foobar" is

All 13 comments

The spec is most probably wrong - I assume that it responds with "application/json" and thus a string like foobar is not allowed (it is not valid JSON) but must have "... If you return plain text you have to change the spec to "text/plain" and this should generate code without JSON deserializiation...

The returned data is valid json and can be parsed using JObject.Parse ok.

A string like foobar is not valid JSON, only "foobar" is

The returned string is properly formatted json
{"dx_deltaJSON":{"dx_data_sets" ... }}
I've checked it can be parsed using JObject.Parse and verified its ok on the Json.Lint website.

The call to result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(responseData_, _settings.Value); will fail when the result type is a string.

Of course, {"dx_deltaJSON":{"dx_data_sets" ... }} is not a string but a complex object. The response however expects a JSON encoded string in the form "asdf"... Can you post the swagger spec of the operation?

I'll look into posting the definition. The response is a valid Json encoded string, see snippet from debug session.
image

Yes, but the Swagger spec describes the response as a single string JSON token, not a complex type with properties like dx_deltaJSON, etc

The swagger definition is available at

https://bitbucket.org/deltaxml/json-compare/raw/681462e9e1ee4fc5661444081e36ebbd9194c6e6/swagger.json

I'm using the "/compare/multi_part_strings" path that has a 200 response defined as
```
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "string"
}

      },

```

In this case the response is a delta json representation of the differences between two json inputs that can have any valid json format. The api just need to pass the string result through to the consumer without further deserialization.

I'm not an expert but the swagger 2.0 spec says the response structure (as defined in the schema) can be a primitive, object or array. In this case the response schema is type string (primitive).
The current implementation using
string result_ = Newtonsoft.Json.JsonConvert.DeserializeObject<string>()
will always throw an exception in this circumstance.

My suggested fix is to tweak the C#Client template Client.Class.ProcessResponse.liquid to handle this scenario. See
template_fix

Here is the updated template

Client.Class.ProcessResponse.liquid.zip

I just started to see this issue too. I think it is fairly new as I haven't seen this issue until I upgraded nswagstudio and started to have see exceptions.

Any more thoughts on this issue and suggested fix?

I wrapped my response in an object called "[MyRequest]Response". Probably a better pattern anyway.

Was this page helpful?
0 / 5 - 0 ratings