Config templates (experimental)
Requires the
template
and desired format Cargo feature.
With our format renderers, you can generate a config template in a specific format. This template will include all fields, default values, comments, metadata, and is useful for situations like scaffolding files during installation.
To utilize, instantiate a generator, add types to render, and generate the output file.
#![allow(unused)] fn main() { use schematic::schema::SchemaGenerator; let mut generator = SchemaGenerator::default(); generator.add::<CustomType>(); generator.generate(output_dir.join("config.json"), renderer)?; }
Supported formats
JSON
The
JsonTemplateRenderer
will render JSON templates without comments. Any commented related options will be force disabled.
#![allow(unused)] fn main() { use schematic::schema::{JsonTemplateRenderer, TemplateOptions}; JsonTemplateRenderer::default(); JsonTemplateRenderer::new(TemplateOptions::default()); }
JSONC
The
JsoncTemplateRenderer
will render JSON templates with comments. We suggest using the .jsonc
file extension, but not
required.
#![allow(unused)] fn main() { use schematic::schema::{JsoncTemplateRenderer, TemplateOptions}; JsoncTemplateRenderer::default(); JsoncTemplateRenderer::new(TemplateOptions::default()); }
Pkl
The
PklTemplateRenderer
will render Pkl templates.
#![allow(unused)] fn main() { use schematic::schema::{PklTemplateRenderer, TemplateOptions}; PklTemplateRenderer::default(); PklTemplateRenderer::new(TemplateOptions::default()); }
TOML
The
TomlTemplateRenderer
will render TOML templates.
#![allow(unused)] fn main() { use schematic::schema::{TomlTemplateRenderer, TemplateOptions}; TomlTemplateRenderer::default(); TomlTemplateRenderer::new(TemplateOptions::default()); }
YAML
The
YamlTemplateRenderer
will render YAML templates.
#![allow(unused)] fn main() { use schematic::schema::{YamlTemplateRenderer, TemplateOptions}; YamlTemplateRenderer::default(); YamlTemplateRenderer::new(TemplateOptions::default()); }
Root document
A template represents a single document, typically for a struct. In Schematic, the last type to be
added to SchemaGenerator
will be the root document, while all other types will be ignored. For
example:
#![allow(unused)] fn main() { // These are only used for type information generator.add::<FirstConfig>(); generator.add::<SecondConfig>(); generator.add::<ThirdConfig>(); // This is the root document generator.add::<LastType>(); generator.generate(output_dir.join("config.json"), renderer)?; }
Caveats
By default arrays and objects do not support default values, and will
render []
and {}
respectively. This can be customized with the
expand_fields
option.
Furthermore, enums and unions only support default values when
explicitly marked as such. For example, with #[default]
.
And lastly, when we’re unsure of what to render for a value, we’ll render null
. This isn’t a valid
value for TOML, and may not be what you expect.
Example output
Given the following type:
#![allow(unused)] fn main() { #[derive(Config)] struct ServerConfig { /// The base URL to serve from. #[setting(default = "/")] pub base_url: String, /// The default port to listen on. #[setting(default = 8080, env = "PORT")] pub port: usize, } }
Would render the following formats:
JSONC | Pkl |
|
|
TOML | YAML |
|
|
Applying the desired casing for field names should be done with serde
rename_all
on the container.
Options
Custom options can be passed to the renderer using
TemplateOptions
.
#![allow(unused)] fn main() { use schematic::schema::TemplateOptions; JsoncTemplateRenderer::new(TemplateOptions { // ... ..TemplateOptions::default() }); }
The
format
option is required!
Indentation
The indentation of the generated template can be customized using the indent_char
option. By
default this is 2 spaces (
).
#![allow(unused)] fn main() { TemplateOptions { // ... indent_char: "\t".into(), } }
The spacing between fields can also be toggled with the newline_between_fields
option. By default
this is enabled, which adds a newline between each field.
#![allow(unused)] fn main() { TemplateOptions { // ... newline_between_fields: false, } }
Comments
All Rust doc comments (///
) are rendered as comments above each field in the template. This can be
disabled with the comments
option.
#![allow(unused)] fn main() { TemplateOptions { // ... comments: false, } }
Header and footer
The header
and footer
options can be customized to add additional content to the top and bottom
of the rendered template respectively.
#![allow(unused)] fn main() { TemplateOptions { // ... header: "$schema: \"https://example.com/schema.json\"\n\n".into(), footer: "\n\n# Learn more: https://example.com".into(), } }
Field display
By default all non-skipped fields in the root document (struct) are rendered in the template. If
you’d like to hide certain fields from being rendered, you can use the hide_fields
option. This
option accepts a list of field names and also supports dot-notation for nested fields.
#![allow(unused)] fn main() { TemplateOptions { // ... hide_fields: vec!["key".into(), "nested.key".into()], } }
Additionally, if you’d like to render a field but have it commented out by default, use the
comment_fields
option instead. This also supports dot-notation for nested fields.
#![allow(unused)] fn main() { TemplateOptions { // ... comment_fields: vec!["key".into(), "nested.key".into()], } }
Field names use the serde cased name, not the Rust struct field name.
Field expansion
For arrays and objects, we render an empty value ([]
or {}
) by
default because there’s no actual data associated with the schema. However, if you’d like to render
a single example item for a field, you can use the expand_fields
option.
#![allow(unused)] fn main() { TemplateOptions { // ... expand_fields: vec!["key".into(), "nested.key".into()], } }
Here’s an example of how this works:
Not expanded | Expanded |
|
|