schemars
schemars copied to clipboard
feat: use enum values as keys for map
This PR fixes https://github.com/GREsau/okapi/issues/128.
When generating a schema for a Map with a key that is an enum, the generated schema only allows keys based off of the enum options. For example,
use schemars::{schema_for, JsonSchema};
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(serde::Serialize, JsonSchema, Debug)]
struct EnumKeyStruct {
key: BTreeMap<Thing, SomeOtherStruct>,
}
#[derive(serde::Serialize, JsonSchema, Debug)]
enum Thing {
Option1,
Option2,
}
#[derive(serde::Serialize, JsonSchema, Debug)]
struct SomeOtherStruct {
key1: String,
key2: u64,
key3: bool,
}
fn main() {
let schema = schema_for!(EnumKeyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
yields:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "EnumKeyStruct",
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"oneOf": [
{
"type": "object",
"required": [
"\"Option1\""
],
"properties": {
"\"Option1\"": {
"$ref": "#/definitions/SomeOtherStruct"
}
}
},
{
"type": "object",
"required": [
"\"Option2\""
],
"properties": {
"\"Option2\"": {
"$ref": "#/definitions/SomeOtherStruct"
}
}
}
]
}
},
"definitions": {
"SomeOtherStruct": {
"type": "object",
"required": [
"key1",
"key2",
"key3"
],
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"key3": {
"type": "boolean"
}
}
},
"Thing": {
"type": "string",
"enum": [
"Option1",
"Option2"
]
}
}
}
This also maintains the original behavior for maps with non-enum keys:
BTreeMap<String, String>
Code
use schemars::{schema_for, JsonSchema};
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(Serialize, JsonSchema, Debug)]
struct PlainMap {
key: BTreeMap<String, String>,
}
fn main() {
let schema = schema_for!(PlainMap);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
Output
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PlainMap",
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
BTreeMap<SomeStruct, String>
Code
use schemars::{schema_for, JsonSchema};
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(serde::Serialize, JsonSchema, Debug)]
struct SomeStruct {
key: BTreeMap<SomeOtherStruct, String>,
}
#[derive(serde::Serialize, JsonSchema, Debug)]
struct SomeOtherStruct {
key1: String,
key2: u64,
key3: bool,
}
fn main() {
let schema = schema_for!(SomeOtherStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
Output
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "SomeOtherStruct",
"type": "object",
"required": [
"key1",
"key2",
"key3"
],
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"key3": {
"type": "boolean"
}
}
}
@GREsau I think I've got this working, I'd appreciate a review!