Code Monkey home page Code Monkey logo

swagger-parser's Introduction

Swagger Parser

NOTE: If you're looking for swagger-parser 1.X and OpenAPI 2.0, please refer to v1 branch

NOTE: Since version 2.1.0 Swagger Parser supports OpenAPI 3.1; see this page for details

Build Master - Java 11, 14 and 17

Table of contents

Overview

This is the Swagger Parser project, which parses OpenAPI definitions in JSON or YAML format into swagger-core representation as Java POJO, returning any validation warnings/errors.

It also provides a simple framework to add additional converters from different formats into the Swagger objects, making the entire toolchain available.

Usage

Using the Swagger Parser is simple. Once included in your project, you can read a OpenAPI Specification from any location:

import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import io.swagger.v3.oas.models.OpenAPI;

// ... your code

  // parse a swagger description from the petstore and get the result
  SwaggerParseResult result = new OpenAPIParser().readLocation("https://petstore3.swagger.io/api/v3/openapi.json", null, null);
  
  // or from a file
  //   SwaggerParseResult result = new OpenAPIParser().readLocation("./path/to/openapi.yaml", null, null);
  
  // the parsed POJO
  OpenAPI openAPI = result.getOpenAPI();
  
  if (result.getMessages() != null) result.getMessages().forEach(System.err::println); // validation errors and warnings
  
  if (openAPI != null) {
    ...
  }
  

or from a string:

import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import io.swagger.v3.oas.models.OpenAPI;

// ... your code

  // parse a swagger description from the petstore and get the result
  SwaggerParseResult result = new OpenAPIParser().readContents("https://petstore3.swagger.io/api/v3/openapi.json", null, null);
  
  // or from a file
  //   SwaggerParseResult result = new OpenAPIParser().readContents("./path/to/openapi.yaml", null, null);
  
  // the parsed POJO
  OpenAPI openAPI = result.getOpenAPI();
  
  if (result.getMessages() != null) result.getMessages().forEach(System.err::println); // validation errors and warnings
  
  if (openAPI != null) {
    ...
  }
  

If you are providing a Swagger/OpenAPI 2.0 document to the parser , e.g.:

SwaggerParseResult result = new OpenAPIParser().readContents("./path/to/swagger.yaml", null, null);

the Swagger/OpenAPI 2.0 document will be first converted into a comparable OpenAPI 3.0 one.

You can also directly use OpenAPIV3Parser which only handles OpenAPI 3.0 documents, and provides a convenience method to get directly the parsed `OpenAPI object:

import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.oas.models.OpenAPI;

// ... your code

  // read a swagger description from the petstore
    
  OpenAPI openAPI = new OpenAPIV3Parser().read("https://petstore3.swagger.io/api/v3/openapi.json");
  

Adding to your project

You can include this library from Sonatype OSS for SNAPSHOTS, or Maven central for releases. In your dependencies:

<dependency>
  <groupId>io.swagger.parser.v3</groupId>
  <artifactId>swagger-parser</artifactId>
  <version>2.1.22</version>
</dependency>

Prerequisites

You need the following installed and available in your $PATH:

After cloning the project, you can build it from source with this command:

mvn package

Authentication

If your OpenAPI definition is protected, you can pass headers in the request:

import io.swagger.v3.parser.core.models.AuthorizationValue;

// ... your code

  // build a authorization value
  AuthorizationValue mySpecialHeader = new AuthorizationValue()
    .keyName("x-special-access")  //  the name of the authorization to pass
    .value("i-am-special")        //  the value of the authorization
    .type("header");              //  the location, as either `header` or `query`

  // or in a single constructor
  AuthorizationValue apiKey = new AuthorizationValue("api_key", "special-key", "header");
  OpenAPI openAPI = new OpenAPIV3Parser().readWithInfo(
    "https://petstore3.swagger.io/api/v3/openapi.json",
    Arrays.asList(mySpecialHeader, apiKey)
  );

Dealing with self-signed SSL certificates

If you're dealing with self-signed SSL certificates, or those signed by GoDaddy, you'll need to disable SSL Trust Manager. That's done by setting a system environment variable as such:

export TRUST_ALL=true

And then the Swagger Parser will ignore invalid certificates. Of course this is generally a bad idea, but if you're working inside a firewall or really know what you're doing, well, there's your rope.

Dealing with Let's Encrypt

Depending on the version of Java that you use, certificates signed by the Let's Encrypt certificate authority may not work by default. If you are using any version of Java prior to 1.8u101, you most likely must install an additional CA in your JVM. Also note that 1.8u101 may not be sufficient on it's own. Some users have reported that certain operating systems are not accepting Let's Encrypt signed certificates.

Your options include:

  • Accepting all certificates per above
  • Installing the certificate manually in your JVM using the keystore using the keytool command
  • Configuring the JVM on startup to load your certificate

But... this is all standard SSL configuration stuff and is well documented across the web.

Options

Parser uses options as a way to customize the behavior while parsing:

1. resolve:

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true); 
final OpenAPI openAPI = new OpenAPIV3Parser().read("a.yaml", null, parseOptions);
  • When remote or relative references are found in the parsed document, parser will attempt to:
  1. resolve the reference in the remote or relative location
  2. parse the resolved reference
  3. add the resolved "component" (e.g. parameter, schema, response, etc.) to the resolved OpenAPI POJO components section
  4. replace the remote/relative reference with a local reference, e.g. : #/components/schemas/NameOfRemoteSchema.

This applies to schemas, parameters, responses, pretty much everything containing a ref.

2. resolveFully:

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true); // implicit
parseOptions.setResolveFully(true);
final OpenAPI openAPI = new OpenAPIV3Parser().read("a.yaml", null, parseOptions);
  • In some scenarios, after references are resolved (with resolve, see above), you might need to have all local references removed replacing the reference with the content of the referenced element. This is for example used in Swagger Inflector. Be aware that the result could be more heavy/long due to duplication

Original document:

a.yaml

openapi: 3.0.1
paths:
  "/newPerson":
    post:
      summary: Create new person
      description: Create new person
      responses:
        '200':
          description: ok
          content:
            "*/*":
              schema:
                "$ref": "./ref-without-component/b.yaml#/components/schemas/CustomerType"

b.yaml

openapi: 3.0.1
components:
  schemas:
    CustomerType:
      type: string
      example: Example value

Serialized result after parsing with option resolveFully(true)

a.yaml

openapi: 3.0.1
servers:
- url: /
paths:
  /newPerson:
    post:
      summary: Create new person
      description: Create new person
      responses:
        200:
          description: ok
          content:
            '*/*':
              schema:
                type: string
                example: Example value
components:
  schemas:
    CustomerType:
      type: string
      example: Example value

3. flatten:

ParseOptions parseOptions = new ParseOptions();
parseOptions.setFlatten(true); 
final OpenAPI openAPI = new OpenAPIV3Parser().read("a.yaml", null, parseOptions);

This is kind of the opposite of resolveFully, limited to defined schemas.

In some scenarios, you might need to have all schemas defined inline (e.g. a response schema) moved to the components/schemas section and replaced with a reference to the newly added schema within components/schemas. This is for example used in Swagger Codegen.

Original document:

flatten.yaml

openapi: 3.0.0
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      responses:
        '200':
          description: An paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                 type: object
                 properties:
                    id:
                      type: integer
                      format: int64
                    name:
                      type: string
                    tag:
                      type: string

Serialized result after parsing with option flatten(true)

openapi: 3.0.0
info:
  title: Swagger Petstore
  license:
    name: MIT
  version: 1.0.0
servers:
- url: /
paths:
  /pets:
    get:
      tags:
      - pets
      summary: List all pets
      responses:
        200:
          description: An paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              style: simple
              explode: false
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/inline_response_200'
components:
  schemas:
    inline_response_200:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string

4. resolveCombinators:

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true); // implicit
parseOptions.setResolveFully(true);
parseOptions.setResolveCombinators(false); // default is true 
final OpenAPI openAPI = new OpenAPIV3Parser().read("a.yaml", null, parseOptions);

This option (only available with resolveFully = true) allows to customize behaviour related to allOf/anyOf/oneOf (composed schemas) processing. With option set to true (default), composed schemas are transformed into "non composed" ones, by having all properties merged into a single resulting schema (see example below). If option is set to false, the resulting schema will instead maintain its "composed" nature, keeping properties within e.g. the allOf members.

Please see examples below:

Unresolved yaml

openapi: 3.0.1
servers:
- url: http://petstore.swagger.io/api

info:
  description: 'This is a sample server Petstore'
  version: 1.0.0
  title: testing source file
  termsOfService: http://swagger.io/terms/

paths:
  "/withInvalidComposedModel":
    post:
      operationId: withInvalidComposedModel
      requestBody:
        content:
          "application/json":
            schema:
              "$ref": "#/components/schemas/ExtendedAddress"
        required: false
      responses:
        '200':
          description: success!
components:
  schemas:
    ExtendedAddress:
      type: object
      allOf:
        - $ref: '#/components/schemas/Address'
        - type: object
          required:
          - gps
          properties:
            gps:
              type: string
    Address:
      required:
      - street
      type: object
      properties:
        street:
          type: string
          example: 12345 El Monte Road
        city:
          type: string
          example: Los Altos Hills
        state:
          type: string
          example: CA
        zip:
          type: string
          example: '94022'

resolvedCombinator = true (default) - Test case

@Test
    public void resolveAllOfWithoutAggregatingParameters(@Injectable final List<AuthorizationValue> auths) {
        ParseOptions options = new ParseOptions();
        options.setResolveFully(true);
        options.setResolveCombinators(true);

        // Testing components/schemas
        OpenAPI openAPI = new OpenAPIV3Parser().readLocation("src/test/resources/composed.yaml",auths,options).getOpenAPI();
        
        ComposedSchema allOf = (ComposedSchema) openAPI.getComponents().getSchemas().get("ExtendedAddress");
        assertEquals(allOf.getAllOf().size(), 2);

        assertTrue(allOf.getAllOf().get(0).get$ref() != null);
        assertTrue(allOf.getAllOf().get(1).getProperties().containsKey("gps"));


        // Testing path item
        ObjectSchema schema = (ObjectSchema) openAPI.getPaths().get("/withInvalidComposedModel").getPost().getRequestBody().getContent().get("application/json").getSchema();

        assertEquals(schema.getProperties().size(), 5);
        assertTrue(schema.getProperties().containsKey("street"));
        assertTrue(schema.getProperties().containsKey("gps"));

    }

resolvedCombinator = true (default) - Resolved Yaml

openapi: 3.0.1
info:
  title: testing source file
  description: This is a sample server Petstore
  termsOfService: http://swagger.io/terms/
  version: 1.0.0
servers:
- url: http://petstore.swagger.io/api
paths:
  /withInvalidComposedModel:
    post:
      operationId: withInvalidComposedModel
      requestBody:
        content:
          application/json:
            schema:
              required:
              - gps
              - street
              type: object
              properties:
                street:
                  type: string
                  example: 12345 El Monte Road
                city:
                  type: string
                  example: Los Altos Hills
                state:
                  type: string
                  example: CA
                zip:
                  type: string
                  example: "94022"
                gps:
                  type: string
        required: false
      responses:
        200:
          description: success!
components:
  schemas:
    ExtendedAddress:
      type: object
      allOf:
      - $ref: '#/components/schemas/Address'
      - required:
        - gps
        type: object
        properties:
          gps:
            type: string
    Address:
      required:
      - street
      type: object
      properties:
        street:
          type: string
          example: 12345 El Monte Road
        city:
          type: string
          example: Los Altos Hills
        state:
          type: string
          example: CA
        zip:
          type: string
          example: "94022"

resolvedCombinator = false - Test case

@Test
   public void resolveAllOfWithoutAggregatingParameters(@Injectable final List<AuthorizationValue> auths) {
       ParseOptions options = new ParseOptions();
       options.setResolveFully(true);
       options.setResolveCombinators(false);

       // Testing components/schemas
       OpenAPI openAPI = new OpenAPIV3Parser().readLocation("src/test/resources/composed.yaml",auths,options).getOpenAPI();
      
       ComposedSchema allOf = (ComposedSchema) openAPI.getComponents().getSchemas().get("ExtendedAddress");
       assertEquals(allOf.getAllOf().size(), 2);
       assertTrue(allOf.getAllOf().get(0).getProperties().containsKey("street"));
       assertTrue(allOf.getAllOf().get(1).getProperties().containsKey("gps"));

       // Testing path item
       ComposedSchema schema = (ComposedSchema) openAPI.getPaths().get("/withInvalidComposedModel").getPost().getRequestBody().getContent().get("application/json").getSchema();
       // In fact the schema resolved previously is the same of /withInvalidComposedModel
       assertEquals(schema, allOf);
       assertEquals(schema.getAllOf().size(), 2);
       assertTrue(schema.getAllOf().get(0).getProperties().containsKey("street"));
       assertTrue(schema.getAllOf().get(1).getProperties().containsKey("gps"));

   }

resolvedCombinator = false - Resolved Yaml

openapi: 3.0.1
info:
title: testing source file
description: This is a sample server Petstore
termsOfService: http://swagger.io/terms/
version: 1.0.0
servers:
- url: http://petstore.swagger.io/api
paths:
/withInvalidComposedModel:
  post:
    operationId: withInvalidComposedModel
    requestBody:
      content:
        application/json:
          schema:
            type: object
            allOf:
            - required:
              - street
              type: object
              properties:
                street:
                  type: string
                  example: 12345 El Monte Road
                city:
                  type: string
                  example: Los Altos Hills
                state:
                  type: string
                  example: CA
                zip:
                  type: string
                  example: "94022"
            - required:
              - gps
              type: object
              properties:
                gps:
                  type: string
      required: false
    responses:
      200:
        description: success!
components:
schemas:
  ExtendedAddress:
    type: object
    allOf:
    - required:
      - street
      type: object
      properties:
        street:
          type: string
          example: 12345 El Monte Road
        city:
          type: string
          example: Los Altos Hills
        state:
          type: string
          example: CA
        zip:
          type: string
          example: "94022"
    - required:
      - gps
      type: object
      properties:
        gps:
          type: string
  Address:
    required:
    - street
    type: object
    properties:
      street:
        type: string
        example: 12345 El Monte Road
      city:
        type: string
        example: Los Altos Hills
      state:
        type: string
        example: CA
      zip:
        type: string
        example: "94022"

Extensions

This project has a core artifact--swagger-parser, which uses Java Service Provider Interface (SPI) so additional extensions can be added.

To build your own extension, you simply need to create a src/main/resources/META-INF/services/io.swagger.v3.parser.core.extensions.SwaggerParserExtension file with the full classname of your implementation. Your class must also implement the io.swagger.v3.parser.core.extensions.SwaggerParserExtension interface. Then, including your library with the swagger-parser module will cause it to be triggered automatically.

OpenAPI 3.1 support

Since version 2.1.0 Swagger Parser supports OpenAPI 3.1; see this page for details

Security contact

Please disclose any security-related issues or vulnerabilities by emailing [email protected], instead of using the public issue tracker.

swagger-parser's People

Contributors

ackintosh avatar actions-user avatar allen-ball avatar barney2k7 avatar boillodmanuel avatar calemroelofssb avatar dependabot[bot] avatar devdevx avatar fehguy avatar fge avatar frantuma avatar fujigon avatar github-actions[bot] avatar gracekarina avatar helmsdown avatar hugomario avatar jehandadk avatar jmini avatar joeljons avatar jonathanparrilla avatar kerrykimbrough avatar mma5997 avatar phiz71 avatar r-sreesaran avatar ralphdoe avatar scottr-ad avatar sullis avatar webron avatar wing328 avatar ymohdriz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swagger-parser's Issues

SwaggerCompatConverter()#read on v 1.2 Doc Showing 0 Paths

Given the following Swagger doc:

$cat /Users/kevin/Workspace/Work/myproject/src/test/resources/swagger_doc_v1.2.json
{
  "apiVersion" : "1.0",
  "swaggerVersion" : "1.2",
  "basePath" : ".",
  "apis" : [
    {
      "path": "/fields",
      "description" : "Resource for fields"
    },
    {
      "path": "/plots",
      "description": "Operation about Plot resource"
    }
  ],
  "info" : {
    "title" : "Location",
    "description" : "Location apis"
  }

Using version 1.0.10, I try to parse it using SwaggerCompatConverter()#read:

scala> uriPath
res4: String = /Users/kevin/Workspace/Work/myproject/src/test/resources/swagger_doc_v1.2.json

scala> new SwaggerCompatConverter().read(uriPath)
java.io.FileNotFoundException: /Users/kevin/Workspace/Work/myproject/src/test/resources/fields (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:708)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1861)
    at io.swagger.parser.SwaggerCompatConverter.readDeclaration(SwaggerCompatConverter.java:437)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:127)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:74)
java.io.FileNotFoundException: /Users/kevin/Workspace/Work/myproject/src/test/resources/plots (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
io.swagger.parser.SwaggerCompatConverter.readDeclaration(SwaggerCompatConverter.java:437)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:127)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:74)
res6: io.swagger.models.Swagger = io.swagger.models.Swagger@a682a8ca

And it shows 0 paths:

scala> res6.getPaths
res8: java.util.Map[String,io.swagger.models.Path] = {}

Am I doing something wrong?

Thanks,
Kevin

SwaggerParser.parse(String swaggerAsString) always returns null

As it delegates to SwaggerParser.parse(String swaggerAsString, List<AuthorizationValue> auths) passing a null value as the second parameter which leads to the conditional statement in this method to always be false.

public Swagger parse(String swaggerAsString) {
    return parse(swaggerAsString, null);
}

public Swagger parse(String swaggerAsString, List<AuthorizationValue> auths) {
    Swagger output;
    try {
        output = new Swagger20Parser().parse(swaggerAsString);
        if (output != null && auths != null && auths.size() > 0) {
            return new SwaggerResolver().resolve(output, auths);
        }
    } catch (IOException e) {
        // continue;
    }
    return null;
}

Not parsing enums in definitions object

Enum fields in definitions object are not being parsed. However, enum fields under a property in definitions object are parsed properly. Example:

swagger.json

"AdvStateType": {
   "description": "Advertising State",
   "enum": [
      "off",
      "on"
   ],
   "type": "string"
},

Corresponding output of - DdebugSwagger in swagger-codegen

"AdvStateType": {
   "type": "string",
   "description": "Advertising State"
},

$ref in swagger-editor running locally

Hi

I am running a local instance of swagger-editor. I had a single yaml file which had no errors in it. I then decided to split the files for each of the paths defined in the single yaml file. Since splitting , I am getting this error in my validator window...

Additional properties not allowed: $ref
Relative paths to the individual endpoints. They must be relative to the 'basePath'.
Jump to line 21
Details
Object
code: "OBJECT_ADDITIONAL_PROPERTIES"
message: "Additional properties not allowed: $ref"
path: Array [1]
description: "Relative paths to the individual endpoints. They must be relative to the 'basePath'."
level: 900

this is the part which is in error
paths:
$ref: '#/paths/index.yaml'

Please advise....

legacy parser's Authorization class has incorrect @JsonTypeInfo

The @JsonTypeInfo is using property = "type" which leads to the type being printed twice when serializing the Authorization Object.

Using the same from http://petstore.swagger.io/api/api-docs, the output of Json.pretty(ResourceListing object) is:

{
  "extraFields" : { },
  "swaggerVersion" : "1.2",
  "apiVersion" : "1.0.0",
  "apis" : [ {
    "extraFields" : { },
    "path" : "/pet",
    "description" : "Operations about pets"
  }, {
    "extraFields" : { },
    "path" : "/user",
    "description" : "Operations about user"
  }, {
    "extraFields" : { },
    "path" : "/store",
    "description" : "Operations about store"
  } ],
  "authorizations" : {
    "oauth2" : {
      "type" : "oauth2",
      "extraFields" : { },
      "type" : "apiKey",
      "scopes" : [ {
        "extraFields" : { },
        "scope" : "write:pets",
        "description" : "Modify pets in your account"
      }, {
        "extraFields" : { },
        "scope" : "read:pets",
        "description" : "Read your pets"
      } ],
      "grantTypes" : {
        "extraFields" : { },
        "implicit" : {
          "extraFields" : { },
          "loginEndpoint" : {
            "extraFields" : { },
            "url" : "http://petstore.swagger.io/api/oauth/dialog"
          },
          "tokenName" : "access_token"
        }
      }
    }
  },
  "info" : {
    "extraFields" : { },
    "title" : "Swagger Sample App",
    "description" : "This is a sample server Petstore server.  You can find out more about Swagger \n    at <a href=\"http://swagger.io\">http://swagger.io</a> or on irc.freenode.net, #swagger.  For this sample,\n    you can use the api key \"special-key\" to test the authorization filters",
    "termsOfServiceUrl" : "http://helloreverb.com/terms/",
    "contact" : "[email protected]",
    "license" : "Apache 2.0",
    "licenseUrl" : "http://www.apache.org/licenses/LICENSE-2.0.html"
  }
}

Notice the oauth2 has "type" repeated.

Seems like the correct fix is to add the @JsonTypeId annotation on getType():
FasterXML/jackson-databind#263

Swagger JSON incorrectly read using system default encoding instead of UTF-8

If a Swagger document has non-ascii characters then those characters are not read correctly by the parser. A Swagger document should probably be encoded UTF-8 because this is the default for JSON. From https://tools.ietf.org/html/rfc7159#section-8.1:
"JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32. The default encoding is UTF-8"

The problem is in io.swagger.parser.util.RemoteUrl. It calls the InputStreamReader constructor that uses the default system charset. This will not necessarily be UTF-8, especially on Windows OS. It should use the InputStreamReader constructor where you can specify both an InputStream and a charsetName.

Errors generating against 1.2 Swagger spec

We are still using Swagger 1.2 because of a regression in Swagger-UI that prevents us from upgrading at this time. I found that the example outlined here https://swagger2markup.readme.io/docs/demo would not work with a 1.2 Swagger definition. So based on the example Gradle script and JUnit test, I created a version that uses SwaggerCompatConverter to parse my file and send the resulting Swagger object to Swagger2MarkupConverter:

Swagger swagger = new SwaggerCompatConverter().read(temp.getAbsolutePath());
Swagger2MarkupConverter
    .from(swagger) 
    .build()
    .intoFolder("src/docs/asciidoc/generated");

When I create the Swagger object, I get a bunch of exceptions logged to standard error, but the JVM does not exit. I reviewed the console output, and I appear to get 1 exception for each endpoint. Here's one example, they all look basically the same:

java.io.FileNotFoundException: /var/folders/g6/plnk0r894t7gd5ch4dkjlttm0000gn/T/repository (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:708)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1846)
    at io.swagger.parser.SwaggerCompatConverter.readDeclaration(SwaggerCompatConverter.java:424)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:125)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:72)
    at com.docfinity.swagger.SwaggerDocGeneratorTests.convertRemoteSwaggerToAsciiDoc(SwaggerDocGeneratorTests.java:96)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

The Swagger2MarkupConverter does complete, but the generated adoc/PDFs are mostly empty and just contain boilerplate stuff like table of contents; none of my API is included.

Here is a gist of my 1.2 swagger definition: https://gist.github.com/rdiehl/3d2405bbcf08006aecb1

I originally logged this with Swagger2Markup, they advised to log it here instead since it's a parser issue.

Official release?

In the readme, it says look in maven central for releases but I don't see any. Is there an official release of the library?

Resource Listing basePath transformation

We encountered a situation where the resource listing includes a basePath property even though it's not part of the spec, and then the resources listed use a "path" relative to the "basePath".

Such an example can be found here - https://mbaas-api.ng.bluemix.net/listings/api-docs

The transformation should include two parts:

  1. Append the "basePath" to each of the resources' "path". For example, in above mentioned sample, "/data" would be transformed to "https://mbaas-api.ng.bluemix.net/listings/data".
  2. The "basePath" property should be removed.

conversion of method response type from Swagger 1.2 to 2.0

For type under operations in Swagger spec 1.2, there seems to be an issue converting it to Swagger 2.0.

Here is the error message returned by Codegen:

reading from https://raw.githubusercontent.com/swagger-api/swagger-parser/master/modules/swagger-compat-spec-parser/src/test/resources/specs/v1_2/singleFile.json

reading from https://raw.githubusercontent.com/swagger-api/swagger-parser/master/modules/swagger-compat-spec-parser/src/test/resources/specs/v1_2/singleFile.json
2366 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for Pet, null
2366 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for Pet, null
2367 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
2367 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for void, null
WARNING!  No property detected!  Falling back to string!
2367 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
WARNING!  No property detected!  Falling back to string!
2367 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for Pet, null
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for void, null
WARNING!  No property detected!  Falling back to string!
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for Pet, null
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for void, null
WARNING!  No property detected!  Falling back to string!
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
2368 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for void, null
WARNING!  No property detected!  Falling back to string!
2370 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
2370 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/Object/Category.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/Object/Pet.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/Object/Tag.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/DefaultApi.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/ApiClient.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/Configuration.pm
writing file /var/tmp/perl/test/lib/WWW/SwaggerClient/Object/BaseObject.pm

My guess is that it fails to covert the response type (void, model or not defined) from 1.2 to 2.0

ref: swagger-api/swagger-codegen#877

Code producing the error log: https://github.com/swagger-api/swagger-core/blob/9c67549cc4e30db916dac0165f0549485a6eb4c7/modules/swagger-models/src/main/java/io/swagger/models/properties/PropertyBuilder.java#L569

Making Deep Copy of `io.swagger.models.Swagger`

I have a need to copy an io.swagger.models.Swagger object.

Rather than write this method in my code (which uses this swagger-parser library), it seems more appropriate for me to make a PR.

Would you accept a PR to make a deep copy of the Swagger object?

Project doesn't compile on the master branch

from the Travis CI log:

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /home/travis/build/swagger-api/swagger-parser/modules/swagger-parser/src/main/java/io/swagger/parser/ResolverCache.java:[6,30] cannot find symbol
  symbol:   class RefConstants
  location: package io.swagger.models.refs
[ERROR] /home/travis/build/swagger-api/swagger-parser/modules/swagger-parser/src/main/java/io/swagger/parser/ResolverCache.java:[32,76] cannot find symbol
  symbol:   variable RefConstants
  location: class io.swagger.parser.ResolverCache
[ERROR] /home/travis/build/swagger-api/swagger-parser/modules/swagger-parser/src/main/java/io/swagger/parser/ResolverCache.java:[33,77] cannot find symbol
  symbol:   variable RefConstants
  location: class io.swagger.parser.ResolverCache

Swagger parser fail to parse the v2.0 example specification

Hi,

I'm testing swagger-codegen with the reference specification example (https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/yaml/petstore.yaml) and it seems it's not working:

~/w/swagger-codegen ❯❯❯ java -jar modules/swagger-codegen-distribution/target/swagger-codegen-distribution-2.1.2-M1.jar -l java -i https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/yaml/petstore.yaml
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
reading from https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/yaml/petstore.yaml
while parsing a block mapping; expected <block end>, but found Scalar;  in 'reader', line 1, column 15:
    swagger: "2.0"info:  version: 1.0.0  title: Sw ... 
                  ^
reading from https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/yaml/petstore.yaml
while parsing a block mapping; expected <block end>, but found Scalar;  in 'reader', line 1, column 15:
    swagger: "2.0"info:  version: 1.0.0  title: Sw ... 
                  ^
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'swagger': was expecting ('true', 'false' or 'null')
 at [Source: swagger: "2.0"info:  version: 1.0.0  title: Swagger Petstore  license:    name: MIThost: petstore.swagger.wordnik.combasePath: /v1schemes:  - httpconsumes:  - application/jsonproduces:  - application/jsonpaths:  /pets:    get:      summary: List all pets      operationId: listPets      tags:        - pets      parameters:        - name: limit          in: query          description: How many items to return at one time (max 100)          required: false          type: integer          format: int32      responses:        200:          description: An paged array of pets          headers:            x-next:              type: string              description: A link to the next page of responses          schema:            $ref: Pets        default:          description: unexpected error          schema:            $ref: Error    post:      summary: Create a pet      operationId: createPets      tags:        - pets      responses:        201:          description: Null response        default:          description: unexpected error          schema:            $ref: Error  /pets/{petId}:    get:      summary: Info for a specific pet      operationId: showPetById      tags:        - pets      parameters:        - name: petId          in: path          description: The id of the pet to retrieve          type: string      responses:        200:          description: Expected response to a valid request          schema:            $ref: Pets        default:          description: unexpected error          schema:            $ref: Errordefinitions:  Pet:    required:      - id      - name    properties:      id:        type: integer        format: int64      name:        type: string      tag:        type: string  Pets:    type: array    items:      $ref: Pet  Error:    required:      - code      - message    properties:      code:        type: integer        format: int32      message:        type: string; line: 1, column: 8]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1419)
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:508)
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1459)
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:683)
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3090)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3036)
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1818)
    at io.swagger.parser.SwaggerCompatConverter.readResourceListing(SwaggerCompatConverter.java:122)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:58)
    at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:34)
    at com.wordnik.swagger.codegen.Codegen.main(Codegen.java:87)
java.lang.RuntimeException: missing swagger input or config!
    at com.wordnik.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:31)
    at com.wordnik.swagger.codegen.Codegen.main(Codegen.java:99)

Did I miss something ?

Regards,
BQ.

Custom Format is not parsed?

Hello, I use the swagger-parser in https://github.com/RobWin/swagger2markup.

I have added an emailAddr with format "email" to the Swagger Petstore example:

"Order": {
            "properties": {
                "id": {
                    "type": "integer",
                    "format": "int64"
                },
                "petId": {
                    "type": "integer",
                    "format": "int64"
                },
                "quantity": {
                    "type": "integer",
                    "format": "int32"
                },
                "shipDate": {
                    "type": "string",
                    "format": "date-time"
                },
                "status": {
                    "type": "string",
                    "description": "Order Status"
                },
                "complete": {
                    "type": "boolean"
                },
                "emailAddr": {
                    "type": "string",
                    "format": "email"
                }
            }

And it seems that the official Swagger parser does not add the emailAddr to the Swagger model:

image

If I have a Model like:

"Order":{
 "properties": {
                "emailAddr": {
                    "type": "string",
                    "format": "email"
                }
            }
}

The properties Map is null:

image

The JsonNode in the parser is correct:

image

The PropertyDeserializer can see the field correctly

image

The problem is in the PropertyBuilder and there StringProperty.isType

  //TODO: implement additional formats
  public static boolean isType(String type, String format) {
    if("string".equals(type) && (format == null || "uri".equals(format) || "byte".equals(format)))
      return true;
    else return false;
  }

There should be some DefaultProperty which is used then, if it's a custom format.

Thanks in advance.
Robert

HTTP 400 when following URLs with path parameters in swagger doc

Using swagger-codegen to read a swagger spec that aggregates other specs with path parameters in the URL, an HTTP 400 is raised because the '{' '}' that delimit the path parameter are not properly encoded by io.swagger.parser.util.RemoteUrl.

This occurs when the Swagger parser determines that the relative path to a resource is described by a string that looks like a URL and it tries to read the contents of the URL into the parser.

java.io.IOException: Server returned HTTP response code: 400 for URL: http://127.0.0.1:8075/api/api-docs/v1/service/{parameter}/otherapi
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1838)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
    at io.swagger.parser.util.RemoteUrl.urlToString(RemoteUrl.java:100)
    at io.swagger.parser.SwaggerCompatConverter.readDeclaration(SwaggerCompatConverter.java:451)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:133)
    at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:36)
    at io.swagger.codegen.Codegen.main(Codegen.java:85)

Parser validation

Is there a way to validate the provided source file and report its warning/errors? Currenlty new SwaggerParser().read() just returns null if parser unable to load the file. Is there a way to return the error while loading the swagger file?

Map primitive string to model

We have the following swagger.json. The POST method just takes a String body and writes it directly into Solr (therefore no real object/datatype). The wagger parser does not map the primitive type string (property) to a Model. Therefore using @RobWin swager2markup generator fails. Is there e specific reson why string property is not mapped to a model?

{
  "apiVersion" : "0.0.1-SNAPSHOT",
  "swaggerVersion" : "1.2",
  "basePath" : "",
  "resourcePath" : "/resource/x/v2",
  "apis" : [ {
    "path" : "/resource/x/v2",
    "operations" : [ {
      "method" : "POST",
      "nickname" : "createX",
      "type" : "string",
      "parameters" : [ {
        "type": "string",
        "description" : "The x in JSON format",
        "paramType" : "body",
        "name" : "body",
        "required" : true
      } ],
      "summary" : "Creates a x x.",
      "notes" : "If id already exists, the x is updated.",
      "responseMessages" : [ {
        "code" : 200,
        "message" : "ok"
      }, {
        "code" : 500,
        "message" : "error"
      } ],
      "consumes" : [ "application/json" ]
    } ]
  }, {
    "path" : "/resource/x/v2/{id}",
    "operations" : [ {
      "method" : "GET",
      "nickname" : "getX",
      "type" : "string",
      "parameters" : [ {
        "type" : "integer",
        "description" : "A valid x x UUID",
        "paramType" : "path",
        "name" : "id",
        "required" : true
      } ],
      "summary" : "Gets the x x with the specified id.",
      "responseMessages" : [ {
        "code" : 200,
        "message" : "ok"
      }, {
        "code" : 404,
        "message" : "not found"
      } ],
      "produces" : [ "application/json" ]
    } ]
  } ]
}

`SwaggerParser#read`'s Behavior with URI

From @kevinmeredith on August 26, 2015 15:49

With "io.swagger" % "swagger-parser" % "1.0.10":

And the following code:

import io.swagger.parser.SwaggerParser
import io.swagger.models.Swagger
import java.net.URI

import scala.util.control.NonFatal

object SwaggerService {

  def getSwaggerObj(swaggerDoc: URI): Either[Throwable, Option[Swagger]] = {
    try {
      Right( Option( new SwaggerParser().read(swaggerDoc.toString) ) )
    }
    catch {
      case NonFatal(e) => Left(e)
    }
  }

I then ran it from Scala's REPL:

scala> new File("/Users/kevin/Workspace/Work/json_sandbox/petstore.json")
res7: java.io.File = /Users/kevin/Workspace/Work/json_sandbox/petstore.json

scala> res7.toURI
res8: java.net.URI = file:/Users/kevin/Workspace/Work/json_sandbox/petstore.json

scala> SwaggerService.getSwaggerObj(res8)
reading from file:/Users/kevin/Workspace/Work/json_sandbox/petstore.json
File 'file:/Users/kevin/Workspace/Work/json_sandbox/petstore.json' does not exist
reading from file:/Users/kevin/Workspace/Work/json_sandbox/petstore.json
File 'file:/Users/kevin/Workspace/Work/json_sandbox/petstore.json' does not exist
res9: Either[Throwable,Option[io.swagger.models.Swagger]] = Right(None)

However, if I cut out the file: from the URI's constructor's String argument, and then make a new URI, it works:

scala> new URI("/Users/kevin/Workspace/Work/json_sandbox/petstore.json")
res12: java.net.URI = /Users/kevin/Workspace/Work/json_sandbox/petstore.json

scala> SwaggerService.getSwaggerObj(res12)
reading from /Users/kevin/Workspace/Work/json_sandbox/petstore.json
res13: Either[Throwable,Option[io.swagger.models.Swagger]] = Right(Some(io.swagger.models.Swagger@657e4ba9))

Since a new URI can be created via java.io.File#toURI, I would've expected my File#toURI-created URI to have worked here, but it didn't.

Copied from original issue: OAI/OpenAPI-Specification#448

Swagger Parser error when reading local yaml files

Hi.

I have used a similar example in terms of hierarchy and $ref definitions as
https://github.com/mohsen1/multi-file-swagger-example

I am new to this, so I am sure I am doing something wrong...Please advise....

When trying to read the yaml file, I am getting this error. Seems like it does not like the $ref definition on the paths/index.yaml file.
Here is the error:
Can not instantiate value of type [simple type, class com.wordnik.swagger.models.Path] from String value ('C:/IDEA/_/_/***/yaml//paths/index.yaml'); no single-String constructor/factory method
at [Source: N/A; line: -1, column: -1](through reference chain: com.wordnik.swagger.models.Swagger["paths"])

Thank you

NPE from SwaggerCompatConverter when required is missing from parameter

2.0 Spec states that required may be missing and hence the use of unwrapped primitive Boolean as return value of io.swagger.models.apideclaration.Parameter#getParameter. Problem is that com.wordnik.swagger.models.parameters.Parameter takes in primitive and autoboxing fails due to null being present.

java.lang.NullPointerException
    at io.swagger.parser.SwaggerCompatConverter.convertParameter(SwaggerCompatConverter.java:183)
    at io.swagger.parser.SwaggerCompatConverter.convertOperation(SwaggerCompatConverter.java:314)
    at io.swagger.parser.SwaggerCompatConverter.convert(SwaggerCompatConverter.java:454)
    at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:111)
    at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:34)
    at com.wordnik.swagger.codegen.Codegen.main(Codegen.java:87)
        ...

swagger-codegen hides this and other exceptions as well (issue swagger-api/swagger-codegen#448)

Swagger Parser not parsing external $refs

The swagger file found at

https://raw.githubusercontent.com/swagger-api/swagger-spec/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions.json

is a example of one that has had it's path object extracted into a separate json file and referenced using a json reference.

paths: {
/pets/{petId}: {
$ref: "https://raw.githubusercontent.com/swagger-api/swagger-spec/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions_part1.json"
}
},

Unfortunately, this does not appear to work as after parsing the swagger file the Path pojo for the /pets/{petId} path contains no defined operations.

I am seeing this in swagger-parser 1.0.8

NullPointerException from SwaggerCompatConverter when operation has null return type

When SwaggerCompatConverter is reading a Swagger 1.2 document that has an operation with a null return type, a NullPointerException is thrown:

java.lang.NullPointerException
at com.wordnik.swagger.models.properties.RefProperty.set$ref(RefProperty.java:44)
at com.wordnik.swagger.models.properties.RefProperty.(RefProperty.java:14)
at io.swagger.parser.SwaggerCompatConverter.propertyFromTypedObject(SwaggerCompatConverter.java:305)
at io.swagger.parser.SwaggerCompatConverter.convertOperation(SwaggerCompatConverter.java:344)
at io.swagger.parser.SwaggerCompatConverter.convert(SwaggerCompatConverter.java:461)
at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:111)
at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:34)
at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:14)

According to Swagger 1.2 Spec, the return type should be "void" for operations that return no value. However, I happen to have one that has "type":null instead of "type":"void". My Swagger document may be incorrect in this sense however the SwaggerCompatConverter should still be more robust. SwaggerCompatConverter should not be passing a null pointer when constructing RefProperty

As a workaround, I am extending SwaggerCompatConverter and overriding propertyFromTypedObject():

@Override
public Property propertyFromTypedObject(ExtendedTypedObject obj) {
    return (obj.getType() == null && obj.getRef() == null)? new RefProperty("void") :
        super.propertyFromTypedObject(obj);
}

'File' type migration

Following #1 - we should write a migrator that does two things if the type is 'File':

  1. Change the consumes field of this operation to "multipart/form-data".
  2. Change the paramType of the parameter to "form".

Handling lists without inner type

for the compat parser:

  1. Anytime we see “type": “List” it should transform it to “type”: “array”. I’ve seen them appear in the following places:
  • responseModel
"responseMessages": [
  {
    "code": 200,
    "message": "OK",
    "responseModel": "List"
  }
  • parameters
{
  "allowMultiple": false,
  "defaultValue": "",
  "description": "reprice",
  "name": "body",
  "paramType": "body",
  "type": "List",
  "required": false
}
  • model properties
"repriceItems": {
  "items": {
    "type": "RepriceItem"
  },
  "required": false,
  "type": "List"
},
  1. When we see “type”: “List” OR “type”: “array” AND we don’t have an “items” key, I’d like to automatically add this:
“items”: {
  “type”: “object”
}

Issue with path parameter encoding when parsing

Have an exception coming from the parser regarding URL encoding for inline parameters:

java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8080/Walletron/api/api-docs/ver1/brands/{brand}/templates
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
at io.swagger.parser.util.RemoteUrl.urlToString(RemoteUrl.java:46)
at io.swagger.parser.SwaggerCompatConverter.readDeclaration(SwaggerCompatConverter.java:367)
at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:104)
at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:34)
at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:14)
at io.github.robwin.swagger2markup.Swagger2MarkupConverter$Builder.(Swagger2MarkupConverter.java:88)
at io.github.robwin.swagger2markup.Swagger2MarkupConverter.from(Swagger2MarkupConverter.java:49)
at io.github.robwin.swagger2markup.Swagger2MarkupConverterTest.testSwagger2AsciiDocConverter(Swagger2MarkupConverterTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
...

The server is expecting the encoded URL, in this case: http://localhost:8080/Walletron/api/api-docs/ver1/brands/%7Bbrand%7D/templates That works just fine and it appears browsers like Chrome and cUrl utilities like Postman do this automatically. I am able however to reproduce the error on a straight curl from the command line.

I'm using 1.0.0

Support for parsing a String into the Swagger model.

Hello,

it would be great to have support for parsing a String (Swagger JSON/YAML) into the Swagger model without the need to store it in a file or retrieve it via an URL.

I would like to reuse the Json.mapper() and Yaml.mapper(), but don't want to have the internal knowledge of the Swagger parser in my code.

Kind regards,
Robert

SwaggerCompatConverter accepts non-Swagger

In general, io.swagger.parser.SwaggerParser.read(String location) appears to return a null pointer if the location is not really a Swagger document. For example, Swagger20Parser checks for the existence of a "swagger" node and returns null if it does not exist. However, SwaggerCompatConverter does not do this. For example, if I give SwaggerCompatConverter.read() the location of a JSON document that is just a an empty object {} then SwaggerCompatConverter returns a Swagger model object. So, there is inconsistent behavior here between Swagger20Parser and SwaggerCompatConverter.

Perhaps SwaggerCompatConverter.readResourceListing() should test for the existence of "swaggerVersion" since that is required according to the SwaggerSpec and return null if it does not exist. This would be consistent with how Swagger20Parser is testing the existence of the "swagger" node. This way the behavior is consistent. It would also be nice if there was a clear javadoc comment, explaining what it means when SwaggerParser.read() throws an IOException vs when it returns a null pointer.

Example field is not parsed

Hi,

I have added 'example' tag to define some example values in swagger. Unfortunatelly the java parser does not handle this. After running the parser in the com.wordnik.swagger.models.Swagger object the example part is empty. It seems that the example part in com.wordnik.swagger.models.Swagger file has a different hierachy than the swagger spec. The swagger editor does not allow the 'example' tag two levels higher as the file would have it. And the file does not have 'example' parameter two levels lower.

Am I right with this bug here?

Thank you.

{
    "swagger": "2.0",
    "info": {
        "title": "Uber API",
        "description": "Move your app forward with the Uber API",
        "version": "1.0.0"
    },
    "host": "api.uber.com",
    "schemes": [
        "https"
    ],
    "basePath": "/v1",
    "produces": [
        "application/json"
    ],
    "paths": {
        "/products": {
            "get": {
                "summary": "Product Types",
                "description": "The Products endpoint returns information about the *Uber* products\noffered at a given location. The response includes the display name\nand other details about each product, and lists the products in the\nproper display order.\n",
                "parameters": [
                    {
                        "name": "latitude",
                        "in": "query",
                        "description": "Latitude component of location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "longitude",
                        "in": "query",
                        "description": "Longitude component of location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    }
                ],
                "tags": [
                    "Products"
                ],
                "responses": {
                    "200": {
                        "description": "An array of products",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/Product",
                                "example": "this is the example"
                            }
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error",
                            "example": "this is the example"
                        }
                    }
                }
            }
        },
        "/estimates/price": {
            "get": {
                "summary": "Price Estimates",
                "description": "The Price Estimates endpoint returns an estimated price range\nfor each product offered at a given location. The price estimate is\nprovided as a formatted string with the full price range and the localized\ncurrency symbol.<br><br>The response also includes low and high estimates,\nand the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code for\nsituations requiring currency conversion. When surge is active for a particular\nproduct, its surge_multiplier will be greater than 1, but the price estimate\nalready factors in this multiplier.\n",
                "parameters": [
                    {
                        "name": "start_latitude",
                        "in": "query",
                        "description": "Latitude component of start location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "start_longitude",
                        "in": "query",
                        "description": "Longitude component of start location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "end_latitude",
                        "in": "query",
                        "description": "Latitude component of end location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "end_longitude",
                        "in": "query",
                        "description": "Longitude component of end location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    }
                ],
                "tags": [
                    "Estimates"
                ],
                "responses": {
                    "200": {
                        "description": "An array of price estimates by product",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/PriceEstimate",
                                "example": "this is the example"
                            }
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error",
                            "example": "this is the example"
                        }
                    }
                }
            }
        },
        "/estimates/time": {
            "get": {
                "summary": "Time Estimates",
                "description": "The Time Estimates endpoint returns ETAs for all products offered at a given location, with the responses expressed as integers in seconds. We recommend that this endpoint be called every minute to provide the most accurate, up-to-date ETAs.",
                "parameters": [
                    {
                        "name": "start_latitude",
                        "in": "query",
                        "description": "Latitude component of start location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "start_longitude",
                        "in": "query",
                        "description": "Longitude component of start location.",
                        "required": true,
                        "type": "number",
                        "format": "double"
                    },
                    {
                        "name": "customer_uuid",
                        "in": "query",
                        "type": "string",
                        "format": "uuid",
                        "description": "Unique customer identifier to be used for experience customization."
                    },
                    {
                        "name": "product_id",
                        "in": "query",
                        "type": "string",
                        "description": "Unique identifier representing a specific product for a given latitude & longitude."
                    }
                ],
                "tags": [
                    "Estimates"
                ],
                "responses": {
                    "200": {
                        "description": "An array of products",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/Product",
                                "example": "this is the example"
                            }
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error",
                            "example": "this is the example"
                        }
                    }
                }
            }
        },
        "/me": {
            "get": {
                "summary": "User Profile",
                "description": "The User Profile endpoint returns information about the Uber user that has authorized with the application.",
                "tags": [
                    "User"
                ],
                "responses": {
                    "200": {
                        "description": "Profile information for a user",
                        "schema": {
                            "$ref": "#/definitions/Profile",
                            "example": "this is the example"
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error",
                            "example": "this is the example"
                        }
                    }
                }
            }
        },
        "/history": {
            "get": {
                "summary": "User Activity",
                "description": "The User Activity endpoint returns data about a user's lifetime activity with Uber. The response will include pickup locations and times, dropoff locations and times, the distance of past requests, and information about which products were requested.<br><br>The history array in the response will have a maximum length based on the limit parameter. The response value count may exceed limit, therefore subsequent API requests may be necessary.",
                "parameters": [
                    {
                        "name": "offset",
                        "in": "query",
                        "type": "integer",
                        "format": "int32",
                        "description": "Offset the list of returned results by this amount. Default is zero."
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "type": "integer",
                        "format": "int32",
                        "description": "Number of items to retrieve. Default is 5, maximum is 100."
                    }
                ],
                "tags": [
                    "User"
                ],
                "responses": {
                    "200": {
                        "description": "History information for the given user",
                        "schema": {
                            "$ref": "#/definitions/Activities",
                            "example": "this is the example"
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error",
                            "example": "this is the example"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "Product": {
            "properties": {
                "product_id": {
                    "type": "string",
                    "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles."
                },
                "description": {
                    "type": "string",
                    "description": "Description of product."
                },
                "display_name": {
                    "type": "string",
                    "description": "Display name of product."
                },
                "capacity": {
                    "type": "string",
                    "description": "Capacity of product. For example, 4 people."
                },
                "image": {
                    "type": "string",
                    "description": "Image URL representing the product."
                }
            }
        },
        "PriceEstimate": {
            "properties": {
                "product_id": {
                    "type": "string",
                    "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles"
                },
                "currency_code": {
                    "type": "string",
                    "description": "[ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code."
                },
                "display_name": {
                    "type": "string",
                    "description": "Display name of product."
                },
                "estimate": {
                    "type": "string",
                    "description": "Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or \"Metered\" for TAXI."
                },
                "low_estimate": {
                    "type": "number",
                    "description": "Lower bound of the estimated price."
                },
                "high_estimate": {
                    "type": "number",
                    "description": "Upper bound of the estimated price."
                },
                "surge_multiplier": {
                    "type": "number",
                    "description": "Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier."
                }
            }
        },
        "Profile": {
            "properties": {
                "first_name": {
                    "type": "string",
                    "description": "First name of the Uber user."
                },
                "last_name": {
                    "type": "string",
                    "description": "Last name of the Uber user."
                },
                "email": {
                    "type": "string",
                    "description": "Email address of the Uber user"
                },
                "picture": {
                    "type": "string",
                    "description": "Image URL of the Uber user."
                },
                "promo_code": {
                    "type": "string",
                    "description": "Promo code of the Uber user."
                }
            }
        },
        "Activity": {
            "properties": {
                "uuid": {
                    "type": "string",
                    "description": "Unique identifier for the activity"
                }
            }
        },
        "Activities": {
            "properties": {
                "offset": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Position in pagination."
                },
                "limit": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Number of items to retrieve (100 max)."
                },
                "count": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Total number of items available."
                },
                "history": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/Activity"
                    }
                }
            }
        },
        "Error": {
            "properties": {
                "code": {
                    "type": "integer",
                    "format": "int32"
                },
                "message": {
                    "type": "string"
                },
                "fields": {
                    "type": "string"
                }
            }
        }
    }
}

Add remote reference resolving

SwaggerParser is the right place for having resolution of remote references. It should not be the default, though, but there should be an option to "ResolveFully" when parsing a spec. In addition, there should be strategies for passing authentication information so the remote references can be read.

The authentication strategy will need some thought, and probably configured by hostname.

SwaggerCompatConverter loses default value for parameters

When SwaggerCompatConverter is reading a Swagger 1.2 document, default values are lost on parameters. This can be seen in the 1.2 version of the petstore example for ""/pet/findByStatus". It has a status parameter with a default value of "available". The problem is in SwaggerCompatConverter.convertParameter().

As a workaround, I am extending SwaggerCompatConverter and overriding convertParameter():

@Override
public Parameter convertParameter(io.swagger.models.apideclaration.Parameter param) {
    Parameter ret = super.convertParameter(param);
    String defaultValue = param.getDefaultValue();
    if (defaultValue != null) {
        if (ret instanceof PathParameter) {
            ((PathParameter) ret).setDefaultValue(defaultValue);
        } else if (ret instanceof QueryParameter) {
            ((QueryParameter) ret).setDefaultValue(defaultValue);
        } else if (ret instanceof HeaderParameter) {
            ((HeaderParameter) ret).setDefaultValue(defaultValue);
        } else if (ret instanceof FormParameter) {
            ((FormParameter) ret).setDefaultValue(defaultValue);
        } else if (ret instanceof CookieParameter) {
            ((CookieParameter) ret).setDefaultValue(defaultValue);
        }
    }
    return ret;
}

missing inner type causes failure in compat lib

if you have a model property like such:

"topics": {
  "type": "array",
  "description": "Topics present in the newsletter"
}

the parser will die because it's expecting items to be populated. Make it friendly. Make it fun

Swagger 2.0 (Petstore) file parsing fails

Parser used:

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-parser</artifactId>
            <version>1.0.5</version>
        </dependency>

File : http://petstore.swagger.io/v2/swagger.json

Error:
reading from http://petstore.swagger.io/v2/swagger.json
com.fasterxml.jackson.databind.node.BooleanNode cannot be cast to com.fasterxml.jackson.databind.node.TextNode (through reference chain: com.wordnik.swagger.models.ModelImpl["properties"]) (through reference chain: com.wordnik.swagger.models.Swagger["definitions"])

SwaggerParser#read Successfully Parses Swagger 1.2 Doc

The io.swagger.parser.SwaggerParser successfully reads the following swagger 1.2 doc:

swagger doc

Note that calling Swagger#getPaths returns a list of size 13.

code

scala> new SwaggerParser().read("http://petstore.swagger.io/api/api-docs")
reading from http://petstore.swagger.io/api/api-docs
reading from http://petstore.swagger.io/api/api-docs
res48: io.swagger.models.Swagger = io.swagger.models.Swagger@8178b58

scala> res48.getPaths.size
res49: Int = 13

For what I'm trying to do (using your OSS library - thank you) is return a size of 3 (for each parent path) and then create operations for each child path.

Is this possible with your library?

Thank you,
Kevin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.