oxidecomputer / typify

compiler from JSON Schema into idiomatic Rust types
Apache License 2.0
418 stars 57 forks source link

Multiple use of `import_types!` causes compilation failures #590

Closed JR-1991 closed 3 months ago

JR-1991 commented 4 months ago

First off, kudos to you for this library! It is very handy and easy to use 🙌

I am currently running into a problem where I want to use the import_types! macro to import multiple schemes. Specifically, I run into the following error using the code below:

import_types!(schema = "models/collection/create_body.json");
import_types!(schema = "models/collection/create_response.json");
the name `error` is defined multiple times
`error` must be defined only once in the type namespace of this module

I figured that one possible solution is to merge both schemes, but I would prefer to keep them separate due to the module's future expansion. Is there a way to achieve this while still using the macro?

Thanks in advance for your support!

ahl commented 4 months ago

Hmmm! Very good point. A workaround is to put both (or one I guess) into a mod, but that's kind of awful.

mod body {
    import_types!(schema = "models/collection/create_body.json");
}
mod response {
    import_types!(schema = "models/collection/create_response.json");
}

This isn't just a problem for the generated error mod. It can also be a problem for the generation of builder and default mods (depending on options and inputs). One solution might be to allow for multiple schema inputs to the import_types! macro... not sure I love that either. Another would be to choose unique names for the generated mods, perhaps based on the name of the input file--I also don't love that!

Any suggestions for an interface you'd prefer?

JR-1991 commented 4 months ago

Thanks for the response and proposed solution. For now, I have gone with putting the response and body into a single schema. It works well!

I agree that these methods are not the most elegant way of handling multiple schemes. A possible solution I could think of would be to have a "main" scheme that references both the body and response schemes. This way, the interface can remain the same, and the schemes can stay separated without causing errors. As far as I know, external references are not possible yet or am I wrong about this?

I thought about something like this for the "main" scheme:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "title": "SomeRequest",
  "type": "object",
  "definitions": {
    "Response": {
      "$ref": "path/to/Response.json"
    },
    "Body": {
      "$ref": "path/to/Body.json"
    }
  }
}
ahl commented 4 months ago

Seems reasonable! In a future where typify supported 1. multiple files and 2. inline schemas, I could image something like this:

import_types!(
    schema = {
        "$defs": {
            "Response": { "$ref": "path/to/Response.json" },
            "Body": { "$ref": "path/to/Body.json" }
        }
    }
);
JR-1991 commented 4 months ago

That's a really elegant solution! Can you give a rough estimate for when external schema refs will be implemented?

ahl commented 3 months ago

That's a really elegant solution! Can you give a rough estimate for when external schema refs will be implemented?

Sorry, I can't. I've been working on #579 little by little, but in my spare time. I'm eager to take a big step forward based on what we've learned from the assumptions and mistakes so far.

JR-1991 commented 3 months ago

No worries, the current workaround does its job, and I am looking forward to the next version!