swagger-api / swagger-api/swagger-codegen

[codegen] response examples not JSONified

Open
#4,896 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

This is a bug encountered whilst writing my own generator which uses examples in the responses part of the swagger.

Response examples are output using Map.toString() rather than being serialised to JSON (as happens for operation-level examples). This is because they are internally deserialised into a Map but never serialised back via ExampleGenerator or similar.

Swagger-codegen version

Bug occurs in swagger-codegen 2.2.1

Swagger declaration file

Say I have a snippet of swagger JSON as follows:

{
    "swagger": "2.0",
    "info": {
        "version": "0.0.0",
        "title": "Cloudant HTTP API"
    },
    "host": "localhost:5984",
    "schemes": [
        "http",
        "https"
    ],
    "consumes": [
        "application/json"
    ],
    "produces": [
        "application/json",
        "text/plain; charset=utf-8"
    ],
    "responses": {
        "202": {
            "description": "Accepted – Document data accepted, but not yet stored on disk",
            "headers": {
                "Cache-Control": {
                    "type": "string"
                },
                "Content-Length": {
                    "type": "integer"
                },
                "Content-Type": {
                    "type": "string"
                },
                "Date": {
                    "type": "string"
                },
                "Server": {
                    "type": "string"
                },
                "Location": {
                    "type": "string",
                    "description": "Database URI location"
                },
                "ETag": {
                    "type": "string",
                    "description": "Quoted new document’s revision"
                }
            },
            "schema": {
                "$ref": "#/definitions/DocumentResponse"
            },
            "examples": {
                "application/json": {
                    "id": "ab39fe0993049b84cfa81acd6ebad09d",
                    "ok": true,
                    "rev": "1-9c65296036141e575d32ba9c034dd3ee"
                }
            }
        },
...

and a mustache template as follows:

{{#operations}}
{{#operation}}
{{#responses}}
{
  "request": {
    "method": {{httpMethod}},
    "urlPattern": {{path}}
  },
  "response": {
    "status": {{code}},
    "jsonBody": {
        {{#examples}}
        {{{example}}}
        {{/examples}}
    },
    "transformers": ["response-template"],
    "headers": {
      "Content-Type": "application/json"
    }
  }
}
{{/responses}}
{{/operation}}
{{/operations}}
Command line used for generation

Custom written generator, so N/A

Steps to reproduce
{
  "request": {
    "method": GET,
    "urlPattern": /_active_tasks
  },
  "response": {
    "status": 200,
    "jsonBody": {
        [{changes_done=64438, database=mailbox, pid=<0.12986.1>, progress=84, started_on=1376116576, total_changes=76215, type=database_compaction, updated_on=1376116619}, {changes_done=14443, database=mailbox, design_document=c9753817b3ba7c674d92361f24f59b9f, pid=<0.10461.3>, progress=18, started_on=1376116621, total_changes=76215, type=indexer, updated_on=1376116650}]
    },
    "transformers": ["response-template"],
    "headers": {
      "Content-Type": "application/json"
    }
  }
}
  • Actual output should resemble JSON in the jsonBody section (note this isn't perfect but it's much closer to the desired output):
{
  "request": {
    "method": GET,
    "urlPattern": /_active_tasks
  },
  "response": {
    "status": 200,
    "jsonBody": {
        "application/json"
        [ {
  "changes_done" : 64438,
  "database" : "mailbox",
  "pid" : "<0.12986.1>",
  "progress" : 84,
  "started_on" : 1376116576,
  "total_changes" : 76215,
  "type" : "database_compaction",
  "updated_on" : 1376116619
}, {
  "changes_done" : 14443,
  "database" : "mailbox",
  "design_document" : "c9753817b3ba7c674d92361f24f59b9f",
  "pid" : "<0.10461.3>",
  "progress" : 18,
  "started_on" : 1376116621,
  "total_changes" : 76215,
  "type" : "indexer",
  "updated_on" : 1376116650
} ]
    },
    "transformers": ["response-template"],
    "headers": {
      "Content-Type": "application/json"
    }
  }
}
Related issues

Couldn't find anything relevant.

Suggested fix

Over-riding postProcessOperations in my generator and cribbing some code from ExampleGenerator got me the "nearly correct" output above:

  @Override
  public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
    // Json prettify the output examples
    @SuppressWarnings("unchecked")
    Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
    @SuppressWarnings("unchecked")
    List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
    for (CodegenOperation operation : operations) {
      List<CodegenResponse> responses = operation.responses;
      for (CodegenResponse response : responses) {
        List<Map<String, Object>> examples = response.examples;
        List<Map<String, Object>> output = new ArrayList<Map<String, Object>>();
        if (examples != null) {
          for (Map<String, Object> example : examples) {
            for (Map.Entry<String, Object> entry : example.entrySet()) {
              final Map<String, Object> kv = new HashMap<String, Object>();
              kv.put("contentType", entry.getKey());
              kv.put("example", Json.pretty(entry.getValue()));
              output.add(kv);
            }
            response.examples = output;
          }
        }
      }
    }
    return objs;
  }

I can contribute a PR if desired but I need to seek permission from my employer first.

Additionally, ExampleGenerator should probably make a better effort at serialisation. For instance if the sample is in XML then it should serialised back to XML, not 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 ExampleGenerator and the response.examples handling shown in postProcessOperations, then compare how operation-level examples are serialized. Update response example processing so JSON examples are emitted as JSON instead of Map.toString() output, and verify the generated custom-template output against the reproduction.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.