Giter VIP home page Giter VIP logo

openapiv3's Introduction

OpenAPI v3 example workflow

This crate provides data structures that represent the OpenAPI v3.0.x specification. Note this does not cover OpenAPI v3.1 which was an incompatible change.

Example

use serde_json;
use openapiv3::OpenAPI;

fn main() {
    let data = include_str!("openapi.json");
    let openapi: OpenAPI = serde_json::from_str(data).expect("Could not deserialize input");
    println!("{:?}", openapi);
}

Goals

  • Provide a deserialization for the specification that maps cleanly to Rust enums etc.

Non Goals

  • Deserialization and subsequent re-serialization are 100% the same.
    • Some defaults show-up when serializing that may not have existed in the input.

Issues

Schemas without a type will end up as any data type as per the specification and can have any parameters of any schema type. Some Open API documents don't include the type parameter it would be nice to try to derive the type but the crate as of right now meets my needs.

Similar Crates

License

This crate is licensed under either of

Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

openapiv3's People

Contributors

6xzo avatar ahl avatar alpire avatar dcjanus avatar ebastien avatar glademiller avatar igorlaboriewefox avatar jakobhellermann avatar jameshinshelwood avatar jcarres-mdsol avatar jessfraz avatar jesskfullwood avatar jonathanmorley avatar killercup avatar msrd0 avatar obmarg avatar swarkentin avatar tiagolobocastro avatar xiphoseer 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

openapiv3's Issues

Add support for dereferencing `$ref`s

Hi, would you please consider adding support for dereferencing $refs?

I created an openapi-fuzzer that uses OpenAPI Specification to generate structured inputs for fuzzing web service. As for now the ReferenceOr<T> objects often contain only strings with a location of given object. I'd would help me if I could resolve the $refs and directly work with structured data.

Schema type Object with OneOf

Hi, I seem to have hit a little snag with this kind of schema:

    ABC:
      type: object
      properties:
        a:
          $ref: '#/components/schemas/A'
        b:
          $ref: '#/components/schemas/B'
        c:
          $ref: '#/components/schemas/C'
      oneOf:
        - required:
            - a
        - required:
            - b
        - required:
            - c

SchemaKind::Type and SchemaKind::OneOf are different derivations so I guess this is not currently supported?

new major version

My intention is to release a new major version in the next week or so. In part this is because my handling of indexmap in #76 was... optimistic. In addition, I'm going to take the opportunity to roll in other breaking changes. I'll be doing an audit of issues and PRs. Feel free to comment on this issue if there are particular changes you'd like to see.

Schema extensions are not parsed

It looks like schema extensions are not parsed, despite support existing in SchemaData::extensions.

@kurtbuilds this issue also affects openapiv3-extended, but that repo currently does not appear to have its issue tracker enabled.

Example

[dependencies]
openapiv3 = "1.0.2"
serde_json = "1.0.96"
serde_yaml = "0.9.21"
openapi: "3.0.3"
info:
  version: "0.1.0"
  title: "Extension"
  description: |
    Extension properties are represented in the data model

paths: {}

components:
  schemas:
    Foo:
      type: object
      properties:
        qty_of_bar:
          type: integer
          name: count
          minimum: 0
use openapiv3::{OpenAPI, SchemaKind, Type};
use serde_json::Value;

#[test]
fn parses_extension() {
    let schema: OpenAPI = serde_yaml::from_str(SCHEMA).unwrap();
    let components = &schema.components.unwrap();
    let foo_schema = components.schemas.get("Foo").unwrap().as_item().unwrap();
    let SchemaKind::Type(Type::Object(foo_schema)) = &foo_schema.schema_kind else {
        panic!("wrong type");
    };
    let qty_bar_schema = foo_schema
        .properties
        .get("qty_of_bar")
        .unwrap()
        .as_item()
        .unwrap();
    let name = qty_bar_schema
        .schema_data
        .extensions
        .get("name")
        .and_then(Value::as_str);
    assert_eq!(name, Some("count"));
}

Expected Outcome

The test passes: count gets parsed into the extensions field.

Actual Outcome

The test fails; name is None.

[src/main.rs:50] &qty_bar_schema = Schema {
    schema_data: SchemaData {
        nullable: false,
        read_only: false,
        write_only: false,
        deprecated: false,
        external_docs: None,
        example: None,
        title: None,
        description: None,
        discriminator: None,
        default: None,
        extensions: {},
    },
    schema_kind: Type(
        Integer(
            IntegerType {
                format: Empty,
                multiple_of: None,
                exclusive_minimum: false,
                exclusive_maximum: false,
                minimum: Some(
                    0,
                ),
                maximum: None,
                enumeration: [],
            },
        ),
    ),
}

Release 0.1.3

Hey, I see that 0.1.3 got updated in cargo.toml a few weeks back. Would you mind publishing it up to crates.io please.

Automatic resolution of `$ref`s

It might be useful for this library to have the ability of resolving $refs. We may want to stop short of making network requests to resolve external documents, but it might be possible to provide an API which allows users to resolve local $refs? I'm not entirely sure what this API should look like though. Obviously an OpenAPI doesn't currently know where it lives on disk (if it even does), so there is no immediate way to decide where to resolve paths from. We could add a function to ReferenceOr which takes a root_dir parameter and resolves it's reference from there?

Version incompatibility when upgrading to 1.0.3

Hey there,

if someone is facing an issue because of indexmap was upgraded as part of a patch version you can just pin this crate like this:

openapiv3 = "=1.0.2" # pinned because paperclip does not support indexmap v2.0.0 which cames with 1.0.3

Thanks for not doing proper semver by expecting everyone just pins all depencies by default. ๐Ÿ‘Ž

Support for extensions

I believe extensions of Openapi v3 would just not be represented in the structures so they get lost in the deserialization of the document.

I suppose that this would need to be supported as some kind of map as there is no way of knowing beforehand the keys.

callbacks should be part of `Operation` object.

Callbacks are often defined inside an Operation of a path. For example take a look at the example here, in this repository and possible other examples.

Right now callbacks are included as part of Components. They should instead be defined under Operation.

Unable to deserialize Stripe API yaml

rustc 1.39.0 (4560ea788 2019-11-04)
openapiv3 = "0.3.0"

Hello! It seems there's an issue with deserializing some paths. I'm attempting to deserialize the Stripe API OpenAPI yaml found here.

My simple test program looks like:

use serde_yaml;
use openapiv3::OpenAPI;

fn main() {
    let data = include_str!("../spec3.sdk.yaml");
    let openapi: OpenAPI = serde_yaml::from_str(data).expect("Could not deserialize input");
    println!("{:?}", openapi);
}

And I'm getting the following error:

thread 'main' panicked at 'Could not deserialize input: Message("data did not match any variant of untagged enum ReferenceOr", Some(Pos { marker: Marker { index: 731702, line: 21072, col: 17 }, path: "paths" }))', src/libcore/result.rs:1165:5

The text indicated by the marker in that output is at the following section of the file:

paths:
  "/v1/3d_secure":

The line is the quoted path "/v1/3d_secure": and the column is the second 'e' right before the quote.

Any help in debugging this would be appreciated. Is there anything else I can provide?

Thank you!

Consider using IndexMap

It would be nice to preserve the order of object keys as provided by the user in the spec - the user can always sort the keys themselves if necessary. It should be a simple change, just swap out the instances of BTreeMap for IndexMap - it has the same API. This is what e.g. serde_json does.

Happy to make a PR if you agree.

Release 0.3.2 breaks compat with 0.3.0

I get a breakage after cargo update which updated 0.3.0 to 0.3.2:

error[E0063]: missing fields `max_length`, `min_length` in initializer of `openapiv3::StringType`
   --> jcli/src/jcli_app/utils/open_api_verifier.rs:398:59
    |
398 |     let valid_schema_kind = SchemaKind::Type(Type::String(StringType {
    |                                                           ^^^^^^^^^^ missing `max_length`, `min_length`

The dependency is listed as openapiv3 = "0.3.0". Cargo has rather looser conventions than standard semver on what versions are considered compatible for ^0.x.y. To avoid unexpected breakage for crate registry users, it's better to increment the minor version also in 0.x when introducing breaking changes.

Links with just an operation_ref fail to deserialise

This minimal example fails to parse with serde_json::from_$

"{\"openapi\":\"\",\"info\":{\"title\":\"\",\"version\":\"\"},\"paths\":{\"\":{\"trace\":{\"responses\":{\"100\":{\"description\":\"\",\"links\":{\"\":{\"operation_ref\":\"\"}}}}}}}}"

This parses:

"{\"openapi\":\"\",\"info\":{\"title\":\"\",\"version\":\"\"},\"paths\":{\"\":{\"trace\":{\"responses\":{\"100\":{\"description\":\"\",\"links\":{\"\":{\"operation_ref\":\"\",\"parameters\":{}}}}}}}}}"

I've been doing proptest generation of schemas to test some logic built on this which is how I discovered the behaviour. I would argue that it is a genuine bug since the spec makes every field in Link optional.

Relatedly, I model the ref/id pair as an Enum, so that proptest knows to generate one of them always : and I'd argue that modelling it as an Enum in opeapiv3 would be better too, but I'm not sure that would help serde figure out whats present when parameters is not present in the doc.

Please tag a release with #60

PR #60 seems fixes some issues with security scheme fields popping up in a spec with 'null' as their value, resulting in validation errors. Any chance - polite request - you can tag a release that includes that PR in the not too distant future?

Thanks!

Code examples please

Hi.
I like your crate.
Could you provide more code examples, please?
For example, how to print all paths and methods (GET, POST ...) extracted from JSON file, please?

data did not match any variant of untagged enum ReferenceOr

Hi,

I have an Open API spec that is 5MB big that NSwag produces for a C# gateway. I run this through a linter and most of the errors I get are around:

a $ref cannot be placed next to any other properties

The NSwag output sample:

        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "nullable": false,
                  "$ref": "#/components/schemas/MessageCollection"
                }
              }
            }
          },

The OpenAPI is generated by a third party so no input in fixing this at the source.

When I run it through this crate, I get:

thread 'main' panicked at src/main.rs:6:55:
Could not deserialize input: Error("data did not match any variant of untagged enum ReferenceOr", line: 64510, column: 3)

I suspect it is the $ref with extra parameters involved.

Is there a way of making the parser/converter more lenient to non-conformances?

Thanks.

ParameterData does not derive Default

There are two structs that don't derive Default: ParameterData and Schema. Schema::default() doesn't really make sense because theres's a required enum SchemaKind in there.

Boxing ReferenceOr<Schema>

Great job on this project btw! I've been trying to bring some openapi v2 bindings as close to this as I can at https://github.com/ctaggart/autorust_openapi. I'm opening this issue because I'm a little confused by boxing in Rust. The last couple of days, I've been running into issues like this:

image

I noticed that it is being done a couple of different ways in this openapiv3:

  • Box<ReferenceOr<Schema>>
  • ReferenceOr<Box<Schema>>

image

This doc says:

Because Boxes implement the Deref<Target=T>, you can use boxed values just like the value they contain.

I've thought about switching everything to Box<ReferenceOr<Schema>> or maybe implementing Deref. I'm not sure if either will work or one is better than the other. Thoughts?

How to set parameter default value

According to openapiv3 parameter spec, a parameter default value can be set by default field , but I can't find relative field in SchemaKind struct, how to describe a default value in parameter in openapiv3 crate?

Two Parameter::Query fields are serialized in snake case

Two fields in Parameter::Query are serialized as snake case, but should be serialized as camelCase. The fields in question are allow_reserved and allow_empty_value.

I checked the rest of the code base and found no other enum struct field cases with this issue.

Keep a changelog

Hi, could you please consider keeping a changelog? It would be easier to look for the changes in one file than looking through commits.

Support for OpenAPI v3.1.x

OpenAPI v3.1.x has some features that would be desirable for us. So it would be neat if this crate could parse OpenAPI v3.1.x documents.

I'm not sure what the best approach for this would be though, particularly if we want to maintain support for OpenAPI v3.0.x in some form.
Perhaps a separate variant of openapiv3::OpenAPI (maybe behind a feature flag) used for representing v3.1 documents instead of v3.0 ones?

Would v3.1.x support be something you'd consider adding to this crate at all? I'd be willing to put in the work if so :)

OAuth2 SecuritySchema flow confusion

Looking at the slack.json schema as an example, OAuth2Flow enums are not deserialized to the appropriate fields in the OAuth2Flows struct. In a snippet of the deserialized types, from the Slack test example, the AuthorizationCode variant gets assigned to the implicit field. They are assigned from their source order to the OAuth2Flows fields, with any excess fields being discarded.

"slackAuth": Item(
    OAuth2 {
        flows: OAuth2Flows {
            implicit: Some(
                AuthorizationCode {
                    authorization_url: "https://slack.com/oauth/authorize",
                    token_url: "https://slack.com/api/oauth.access",
                    refresh_url: None,
                    scopes: {
                        "admin": "admin",
                        "bot": "Bot user scope",

I haven't looked closely as to why yet (outside of OAuth2Flow being an enum), but wanted to get this noted down first.

Release 0.3.3 breaks compat with 0.3.2

Just like you realized last release (#20), adding fields to a struct when all fields are public is a breaking change. The following code compiles with 0.3.2 but fails to compile with 0.3.3:

use openapiv3::Info;

fn main() {
        let api_info = Info {
                title: "Test".to_owned(),
                description: Some("Test Specification".to_owned()),
                terms_of_service: None,
                contact: None,
                license: None,
                version: "0.0.0".to_owned()
        };
}

Maybe next time you need to change your test code because it fails to compile, consider it a warning sign that your changes are indeed breaking changes: 1e009b2#diff-a7301f9a3dcd2e25ff77be69aa773585260086ada5c48a4b87c512aca41b1ba6R91

Parameter style

Hi,

First of all massive thanks for this project! I'm converting openapiv2 to openapiv3 on a project and I really enjoyed using this implementation with a less ambiguity than the v2 I'm using which makes things easier :)

A couple of questions, on the Parameter could the style deserialize be skipped if it's at it's default value, or maybe could be made an Option? From the spec: "Default values (based on value of in): for query - form; for path - simple; for header - simple; for cookie - form."

Thanks!

Some vectors contain Option<?>

Some vectors such as StringType::enumeration are defined as Vec<Option<String>>, why have a list of potential strings?

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.