swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.98k stars 6.03k forks source link

[codegen] .yaml input files containing a tab character are -- without warning -- erroneously treated as JSON #6490

Open ianfixes opened 7 years ago

ianfixes commented 7 years ago

Description

Codegen fails to provide an error message when YAML parsing fails -- e.g. if they have a tab value in a string value (not indentation).

The assumption is that such parse errors indicate that the file is really JSON, and that may produce desired behavior in many cases. However, for YAML files with light formatting errors, this behavior gives the mistaken impression that swagger-codegen simply doesn't understand YAML. Parsing YAML as JSON just isn't possible.

This is especially confusing behavior, because not all YAML parsers choke on tabs in this way (i.e. I was able to use yaml2json on the same file without incident, and the resulting JSON was accepted by swagger-codegen).

Swagger-codegen version

2.2.2 on OSX, installed via Homebrew

Swagger declaration file content or url

my-input.yaml:

swagger: '2.0'
info:
  description:  The first character after the colon on this line is a tab

Command line used for generation

swagger-codegen generate -i my-input.yaml -l ruby -v

Example:

 $ swagger-codegen generate -i my-input.yaml -l ruby -v
[main] INFO io.swagger.codegen.config.CodegenConfigurator - 
VERBOSE MODE: ON. Additional debug options are injected
 - [debugSwagger] prints the swagger specification as interpreted by the codegen
 - [debugModels] prints models passed to the template engine
 - [debugOperations] prints operations passed to the template engine
 - [debugSupportingFiles] prints additional data passed to the template engine
[main] INFO io.swagger.parser.Swagger20Parser - reading from testrail-swagger.yaml
[main] INFO io.swagger.parser.Swagger20Parser - reading from testrail-swagger.yaml
[main] ERROR io.swagger.parser.SwaggerCompatConverter - failed to read resource listing
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'swagger': was expecting ('true', 'false' or 'null')
 at [Source: testrail-swagger.yaml; line: 1, column: 9]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702)
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3524)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2686)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:878)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:772)
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3834)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3783)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2431)
    at io.swagger.parser.SwaggerCompatConverter.readResourceListing(SwaggerCompatConverter.java:189)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:116)
    at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:74)
    at io.swagger.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:419)
    at io.swagger.codegen.cmd.Generate.run(Generate.java:232)
    at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:41)
Exception in thread "main" java.lang.RuntimeException: missing swagger input or config!
    at io.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:651)
    at io.swagger.codegen.cmd.Generate.run(Generate.java:234)
    at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:41)

Steps to reproduce

  1. Save the snippet above to my-input.yaml. Note that there is a tab character on the last line between the : and the T.
  2. swagger-codegen generate -i my-input.yaml -l ruby -v

Expected behavior: Successful code generation or YamlParseException Actual behavior: JsonParseException

Note that according to the YAML spec, "tabs are forbidden". It's entirely reasonable for swagger to reject my file, but it should do so with some explicit messaging as to the YAML error.

Continuing

  1. yaml2json my-input.yaml > my-input.json
  2. swagger-codegen generate -i my-input.json -l ruby

Expected behavior: Successful code generation Actual behavior: Successful code generation

Related issues/PRs

None that I could find in about 4 minutes of looking. And by that I mean: I saw a few hundred issues in searches for "yaml" and "json", but I was unqualified to claim that they were the same as this issue without attempting to reproduce each individual one.

Suggest a fix/enhancement

If a file is being parsed as YAML (based on its extension or whatever swagger uses to detect the format), and that parsing fails, print that parse error to STDERR before falling back on the JSON parser.

If verbose mode is on, say explicitly that "YAML parsing failed".

svetozar02 commented 7 years ago

+1

mbystryantsev commented 6 years ago

+1

gubespam commented 3 years ago

+1