glademiller / openapiv3 Goto Github PK
View Code? Open in Web Editor NEWRust Open API v3 Structs and Enums for easy deserialization with serde
License: Apache License 2.0
Rust Open API v3 Structs and Enums for easy deserialization with serde
License: Apache License 2.0
Hi, would you please consider adding support for dereferencing $ref
s?
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 $ref
s and directly work with structured data.
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?
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.
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.
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?
Currently the Reference
variant of ReferenceOr
only contains a reference
string. To accord with the spec, it should also include description
and status
fields.
Hi there,
There is an optional field called PathItems in in components. https://spec.openapis.org/oas/latest.html#fixed-fields-5
It is missing in components in this lib
https://github.com/glademiller/openapiv3/blob/master/src/components.rs
According to the OpenAPI specification, the Schema
object should support extensions - https://swagger.io/specification/#schema-object
This object MAY be extended with Specification Extensions.
This change: 1eda5d6 looks wrong to me.
The openapi spec, under "Schema Object" -> "Properties" says:
items - ... items MUST be present if the type is array.
What was the reason for the change?
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.
It might be useful for this library to have the ability of resolving $ref
s. 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 $ref
s? 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?
SchemaData is missing a field to hold Discriminator object
OpenApiV3 currently does not handle patternProperties.
See exemple from open api from GitHub : https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v3.0
This is standard JsonSchema: https://json-schema.org/understanding-json-schema/reference/object.html#patternproperties
Maybe i can help fix it.
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.
[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"));
}
The test passes: count
gets parsed into the extensions field.
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: [],
},
),
),
}
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
.
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.
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!
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.
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?
Would be very handy to allow for them to be stored as keys in Hash{Map,Set}
s.
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.
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.
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:
I noticed that it is being done a couple of different ways in this openapiv3:
Box<ReferenceOr<Schema>>
ReferenceOr<Box<Schema>>
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?
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. ๐
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.
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!
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
Hi, could you please consider keeping a changelog? It would be easier to look for the changes in one file than looking through commits.
Some vectors such as StringType::enumeration
are defined as Vec<Option<String>>
, why have a list of potential strings?
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!
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 :)
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.
Thanks for the lib.
According to the spec, I believe the Response
object's content
field should not be a ReferenceOr<MediaType>
but just a bare MediaType
.
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.