Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
142 stars 166 forks source link

Generated RestClient Incorrectly Serializes Request Body #5062

Open jacksonkays opened 2 months ago

jacksonkays commented 2 months ago

Describe the issue or request Utilizing Autorest v3 C# to generate REST clients based on an OpenAPI 3.0 Swagger JSON specification is resulting in certain input values for a given object to be serialized incorrectly. In the specification, the object has a 'value' property that can receive any JSON-supported data type (number, boolean, array of any data type, object, string), but when passing in array or object types as the 'value' property, the JSON writer malformats them into a collection of square and curly brackets. Stepping through the code it seems to make assumptions that the object and array types are Newtonsoft.Json.JArray and Newtonsoft.Json.JObject types, and then fails to enumerate over the array values, and then assumes the JObject type to be an array as opposed to a key value pair enumerable.

Here's what the array types look like before and after the writer attempts to serialize them into the request. Before:

[
  "test1",
  "test2"
]

After:

[
  [],
  []
]

Here's what the object type looks like: Before:

{
  "key1": "value1",
  "key2": "value2"
}

After:

[
  [
    []
  ],
  [
    []
  ]
]

Describe your ideas for solutions Understanding why the switch case for Utf8JsonWriter.WriteObjectValue classifies JObject types as array types (Enumerable instead of enumerable key value pairs), and why Utf8JsonWriter.WriteObjectValue is unable to parse the JValues (items) within each JArray.

My workaround currently is just editing the generated client to serialize using a number of custom Newtonsoft JsonConverters, and I have not found a solution using the System.Text.Json or System.Text.Json.Serialization packages.

jacksonkays commented 2 months ago

A couple of the spec changes I've made to try to resolve this are:

          "value": {
            "description": "The output value",
            "type": "object"
          },
          "value": {
            "description": "The output value",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "boolean"
              },
              {
                "type": "number"
              },
              {
                "type": "object"
              }
            ]
          },
          "value": {
            "description": "The output value",
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/AnyValue"
            }
          },

with the AnyValue schema described as

"AnyValue": {}

This is based off of the following OpenAPI documentation: https://swagger.io/docs/specification/data-models/data-types/ https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/

ArcturusZhang commented 1 month ago

Hi @jacksonkays thanks for this issue. Could you specify whether which is the case?

Also could you share a bit about how the generated code looks like and your changes on it? Or share a spec so that we could reproduce it.

And FYI this generator is never made to officially support OpenAPI v3, some of them might work, but some of them might not work.