paperclip icon indicating copy to clipboard operation
paperclip copied to clipboard

Fails to deserialize sample YAML v2 document

Open pwoolcoc opened this issue 4 years ago • 8 comments

The sample YAML document on this page: https://swagger.io/docs/specification/2-0/basic-structure/ cannot be deserialized by paperclip, it errors out here:

---- test_basic_structure stdout ----
thread 'test_basic_structure' panicked at 'Couldn't deser doc: Yaml(Message("invalid type: integer `200`, expected a string", Some(Pos { marker: Marker { index: 183, line: 14, col: 7 }, path: "paths./users" })))', src/lib.rs:41:45
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Here is the code I used to generate this error:

use paperclip::v2::{self, ResolvableApi, DefaultSchema, models::Version};

#[test]
fn test_basic_structure() {
    use std::io::{self, Cursor};

    let doc = r#"swagger: "2.0"
info:
  title: Sample API
  description: API description in Markdown.
  version: 1.0.0

host: api.example.com
basePath: /v1
schemes:
  - https

paths:
  /users:
    get:
      summary: Some text
      description: Some more text
      produces:
        - application/json
      responses:
        200:
          description: OK"#.to_string();

    let bytes = doc.as_bytes().to_vec();
    let mut bytes = Cursor::new(bytes);

    let api: ResolvableApi<DefaultSchema> = v2::from_reader(&mut bytes).expect("Couldn't deser doc");
    assert_eq!(api.swagger, Version::V2);
}

pwoolcoc avatar Jun 09 '20 19:06 pwoolcoc

As the error says, you should have "200" (string) instead of 200 (integer) in responses schema.

wafflespeanut avatar Jun 10 '20 10:06 wafflespeanut

ok, but this sample is not from me, but from the official OpenAPIv2 spec...not accepting 200 means paperclip is not spec-compliant.

pwoolcoc avatar Jun 10 '20 10:06 pwoolcoc

The official spec seems to describe the status code as a string (example here). The JSON schema for v2 spec also says that the responses schema is an object, which only have string keys.

wafflespeanut avatar Jun 10 '20 10:06 wafflespeanut

exactly, so the 200 should be parsed as a string instead of integer, but it's not, that's where the issue is.

pwoolcoc avatar Jun 10 '20 10:06 pwoolcoc

Um, no. The 200 should be written as a string in the spec (it will be parsed as an integer, but it should still be "200" in the spec).

wafflespeanut avatar Jun 10 '20 10:06 wafflespeanut

At the end of the day, the document above is a spec-compliant document, as it was taken directly from the spec. All other OpenAPI validators I've run it through have successfully validated it. Only the 2 rust crates I have tried, yours and the openapi crate, have failed to parse it. My use case involves accepting arbitrary OpenAPI documents from my users, so I need to be able to accept any valid OpenAPI spec, and therefore paperclip isn't an option as long as it won't accept all valid OpenAPI specs.

pwoolcoc avatar Jun 10 '20 12:06 pwoolcoc

Okay, I guess it doesn't hurt to deviate a little from the spec and relax the check with an enum of integer/string.

This is now open for anyone to work on!

wafflespeanut avatar Jun 10 '20 18:06 wafflespeanut

So I've looked into this, and there seems to be an issue with serde. Specifically, a struct that has a #[serde(flatten)] property of BTreeMap<_, BTreeMap<String, _>> doesn't automatically cast numbers to Strings, while a struct with the same property without a #[serde(flatten)] attribute does.

Example: https://gist.github.com/mxndtaylor/488db8ca053d8d69e72fa0fc4f5d0a23

mxndtaylor avatar Aug 29 '22 19:08 mxndtaylor