Conversation
  thread 'main' (478016) panicked at build.rs:16:46:
  failed to parse: tmp/ojf.json: Error("invalid type: sequence, expected a string", line: 1191, column: 8)

That's serde_json trying to parse the OnlyJunk.Fans OpenAPI json (pretty printed with jq).

Line 1191 is:

      },

The entire thing is perfectly valid JSON. It's big, though, but... that shouldn't be much of an issue. Right? Right?

2
0
0

@algernon Did you make a mistake when generating the json? What does other json parsers think of it?

1
0
0

@loke The JSON is valid. jq likes it, so does pretty much everything else I threw at it.

0
0
0

If I rearrange the JSON to have the problematic part elsewhere, it consistently fails at the same place: wherever I moved these parts.

1
0
1

If I remove everything under {"components": {"schemas": {}}}, then serde_json has no trouble with the rest.

Now to figure out which part of the schemas trigger the problem.

1
0
1

Reproducer:

{
  "components": {
    "schemas": {
      "SomeType": {
        "properties": {
          "email": {
            "type": []
          }
        }
      }
    }
  }
}

If I change "type": [] to say, "x-type": [], then it parses. If I remove a level, it parses.

2
0
1

@algernon i would suggest it being about the rust keyword type but it can’t possibly be that

1
0
0

If I change the keys to a, b, c, d, e respectively, and leave type as-is, it parses.

If I just change components to component, it parses.

1
0
1

@algernon exactly what the hell

0
0
0

@tauon It's not. The same key appears elsewhere and is fine. It's also fine if I change any of the other keys.

0
0
1

Oh. Fun. It is not serde_json's fault. It tries to deserialize into a type provided by progenitor, and that fails.

It can deserialize fine into serde_json::Value.

1
0
1

It's not even progenitor's fault, either.

let spec: openapiv3::OpenAPI =
  serde_json::from_str(&reproducer)
    .unwrap();

This blows up too.

2
0
1

Which kind of makes sense, because the generated json is for OpenAPI 3.1.0, while the openapiv3 crate only supports 3.0.0. There's a draft pull request adding 3.1.0 support open since 2022.

So, uhh. This isn't going to be fixed anytime soon I guess.

1
0
1

So: can I talk utoipa into generating 3.0 instead of 3.1, I wonder?

1
0
1

@buherator Yeah, it turned out to be a 3.0 vs 3.1 incompatibility, and underlying crates only supporting 3.0, while my spec is 3.1.

0
0
2

There are 3.1 -> 3.0 downgrade tools, though.

1
0
0

Nice. Getting somewhere. Now I need to fix the spec. :)

1
0
0

Nice. Spec fixed. But progenitor doesn't support multipart/form-data yet. That may take a while. But some progress was made towards an API client, so that's something!

I could use another language for the API client, one where a suitable generator (preferably from OpenAPI 3.1) is available. But... I don't want to, and I don't care enough. I'll revisit this around OnlyJunk.Fans 1.0 or something.

1
0
0
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

use reqwest::header;

#[tokio::main]
async fn main() {
    let token = std::env::var("OJF_DEMO_TOKEN").expect("$OJF_DEMO_TOKEN not set");
    let auth_header = format!("Bearer {token}");

    let mut headers = header::HeaderMap::new();
    headers.insert(
        header::AUTHORIZATION,
        auth_header.parse().expect("Authorization header value failed to parse"),
    );

    let client = reqwest::ClientBuilder::new()
        .default_headers(headers)
        .build()
        .expect("failed to build reqwest client");

    let client = Client::new_with_client("http://127.0.0.1:8084", client);

    let resp = client.account_view().send().await.unwrap();
    println!("{resp:#?}");
}

=>

❯ cargo run -q
AccountResponse {
    email: "demo@onlyjunk.fans",
}

Not bad. Due to multipart/form-data being unsupported, this won't be able to cover the entire API, but it can cover a large enough area. This will help me build some small tooling to help with admin tasks in the near future, replacing a handful of shell scripts that drive curl in various ways.

0
0
0