4 releases
0.1.4 | Feb 3, 2024 |
---|---|
0.1.3 | Nov 12, 2023 |
0.1.2 |
|
0.1.1 | Dec 27, 2022 |
0.1.0 | Dec 27, 2022 |
#615 in Encoding
36 downloads per month
56KB
1K
SLoC
jtd-derive
Generate JSON Type Definition schemas from Rust types.
Status
Sort of usable, but lacking important features like better serde
support.
The API is unstable. Expect breaking changes between minor version bumps.
Why?
Because Typedef seems really nice in how minimal and unambiguous it is. In particular, systems that generate JSON-based APIs and related IDL files (with the expectation those will be used for code generation) could use something like this. Feature bloat is arguably not a good idea in those sensitive spots.
This crate hopefully makes it a little nicer in that Rust projects can keep language-agnostic type definitions as Rust code rather than a separate thing with a different syntax.
Alternatives
JSON Schema
JSON Schema is often tauted as the more universally accepted solution. The thing is, it's a solution to a different problem. JSON Schema is meant to be very expressive and good for validating JSON data against complex constraints.
If you expect codegen to be a major need for you but want to provide JSON
Schemas as well, consider using Typedef and writing a Typedef -> JSON Schema
generator. That way codegen consumers can still benefit from Typedef's
simplicity.
Types supported by serde
, but not by jtd_derive
- unit structs like
struct Foo;
- tuple structs like
struct Foo(u32, u32)
orstruct Foo()
- Newtype structs are an exception. They are represented as the inner value in
JSON, and as the inner schema in Typedef. A struct is considered a newtype
simply if it has exactly one unnamed field, e.g.
struct Foo(u32)
- Newtype structs are an exception. They are represented as the inner value in
JSON, and as the inner schema in Typedef. A struct is considered a newtype
simply if it has exactly one unnamed field, e.g.
- structs in the C struct style, but with no fields, e.g.
struct Foo {}
- enums with mixed variant "kinds", e.g.
enum Foo { Bar, // unit variant Baz { x: u32 }, // struct variant }
- enums with tuple variants, e.g.
enum Foo { Bar(u32), Baz(String), }
- enums with any other
serde
representation than internally tagged - that's how Typedef insists enums are represented - tuples - serialized as potentially heterogenous arrays, but Typedef only supports homogenous ones.
Bound
- one variant gets serialized as a string, the others as objects. Typedef can't support that kind of decadent fancy.Duration
- usesu64
, which is unsupported by Typedef.SystemTime
- same reason as above.PhantomData
- seems silly to try to serialize that! Also no good way to specify a null literal in the schema.Result
-Ok
andErr
variants usually have different forms, which can't be expressed in Typedef.OsStr
,OsString
,Path
,PathBuf
- I don't fully understand the subtleties around these types. I'm not sure if it's smart to encourage people to use these types at API boundaries other than the Rust FFI. If you'd like to discuss, feel free to open an issue describing your use case and thoughts.
This may all seem quite restrictive, but keep in mind the point of Typedef isn't to be vastly expressive and capable of describing anything that can be described with the Rust type system. The idea is to encourage APIs that are universal and schemas that are suitable for code generation.
Every bit of expressiveness you're missing here is a breath of relief for your consumers.
License
Dual licensed under MIT and Apache 2.0 at your option, like most Rust project.
Dependencies
~2.3–3.5MB
~73K SLoC