Here is my struct
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema)]
pub struct Position {
x: SignedDecimal,
y: SignedDecimal,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema)]
pub struct SignedDecimal {
value: Decimal256,
sign: bool,
}
An example output of the default schema looks like this:
{
"x": { "value": "1.5", "sign": true },
"y": { "value": "1.5", "sign": true }
}
What I want it to look like is this:
{
"x": "1.5",
"y": "1.5"
}
But I can't seem to get the Schemars macros to do what I want. I've tried many things, like this for example:
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema)]
#[schemars(schema_with = "String")]
pub struct SignedDecimal {
value: Decimal256,
sign: bool,
}
Ideally I am not using any additional macros on the Position struct, and instead just modifying the SignedDecimal struct. All of the relevant String impls have been defined, I just can't make the macro do what I want.
CodePudding user response:
You could overwrite the schema for fields with #[schemars(schema_with = "…")]
. For example:
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema)]
pub struct Position {
#[schemars(schema_with = "pretend_to_be_number_string")]
x: SignedDecimal,
#[schemars(schema_with = "pretend_to_be_number_string")]
y: SignedDecimal,
}
fn pretend_to_be_number_string(
gen: &mut schemars::gen::SchemaGenerator,
) -> schemars::schema::Schema {
use schemars::schema::*;
let mut obj = SchemaObject::default();
obj.instance_type = Some(SingleOrVec::Single(InstanceType::String.into()));
obj.string().pattern = Some("[ -]?[0-9]*\\.[0-9]*".into()); // TODO: rudimentary
let obj = Schema::Object(obj);
gen.definitions_mut()
.insert("SignedDecimal".into(), obj.clone());
let mut or = SchemaObject::default();
or.reference = Some("#/definitions/SignedDecimal".into());
Schema::Object(or)
}
will result in the schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Position",
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"$ref": "#/definitions/SignedDecimal"
},
"y": {
"$ref": "#/definitions/SignedDecimal"
}
},
"definitions": {
"SignedDecimal": {
"type": "string",
"pattern": "[ -]?[0-9]*\\.[0-9]*"
}
}
}
There is probably a way of not having to specify this on every field, but I can't find it.
CodePudding user response:
Not a perfect solution but I'm going to manually implement JsonSchema since I can't figure out how to make it work with the provided macros.
impl JsonSchema for SignedDecimal {
fn schema_name() -> String {
"signed_decimal".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(gen)
}
fn is_referenceable() -> bool {
true
}
}