Marwes / schemafy

Crate for generating rust types from a json schema

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Type is Option<serde_json::Value> instead of Option<String>

waywardmonkeys opened this issue · comments

In the Vega Lite schema, there is this property on an Axis:

        "title": {
          "description": "A title for the field. If `null`, the title will be removed.\n\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`).  If the field has an aggregate function, the function is displayed as a part of the title (e.g., `\"Sum of Profit\"`). If the field is binned or has a time unit applied, the applied function will be denoted in parentheses (e.g., `\"Profit (binned)\"`, `\"Transaction Date (year-month)\"`).  Otherwise, the title is simply the field name.\n\n__Note__: You can customize the default field title format by providing the [`fieldTitle` property in the [config](config.html) or [`fieldTitle` function via the `compile` function's options](compile.html#field-title).",
          "type": [
            "string",
            "null"
          ]
        },

This is coming out in the generated Rust as:

    /// A title for the field. If `null`, the title will be removed.
    ///
    /// __Default value:__  derived from the field's name and transformation function (`aggregate`,
    /// `bin` and `timeUnit`).  If the field has an aggregate function, the function is displayed
    /// as a part of the title (e.g., `"Sum of Profit"`). If the field is binned or has a time unit
    /// applied, the applied function will be denoted in parentheses (e.g., `"Profit (binned)"`,
    /// `"Transaction Date (year-month)"`).  Otherwise, the title is simply the field name.
    ///
    /// __Note__: You can customize the default field title format by providing the [`fieldTitle`
    /// property in the [config](config.html) or [`fieldTitle` function via the `compile`
    /// function's options](compile.html#field-title).
    pub title: Option<serde_json::Value>,

I really think that should be Option<String> though?

Perhaps related to this is this:

        "legend": {
          "anyOf": [
            {
              "$ref": "#/definitions/Legend"
            },
            {
              "type": "null"
            }
          ],
          "description": "An object defining properties of the legend.\nIf `null`, the legend for the encoding channel will be removed.\n\n__Default value:__ If undefined, default [legend properties](legend.html) are applied."
        },

Which gets translated to:

pub legend: Option<serde_json::Value>,

But I think that should be Option<Legend>.

There is a bit of code that handles anyOf where there can either be just an element of some type or an array of that type

schemafy/src/lib.rs

Lines 307 to 324 in 7871e21

} else if typ.any_of.as_ref().map_or(false, |a| a.len() == 2) {
let any_of = typ.any_of.as_ref().unwrap();
let simple = self.schema(&any_of[0]);
let array = self.schema(&any_of[1]);
if !array.type_.is_empty() {
if let SimpleTypes::Array = array.type_[0] {
if simple == self.schema(&array.items[0]) {
return FieldType {
typ: format!("Vec<{}>", self.expand_type_(&any_of[0]).typ),
attributes: vec![
format!(r#"with="{}one_or_many""#, self.schemafy_path),
],
default: true,
};
}
}
}
return "serde_json::Value".into();

or it falls back to emitting serde_json::Value

You would want to extend that bit to check for "type": "null" + some other type and then emit an Option<some other type>

Thanks! I started looking at this this evening. I will poke at it more and submit a PR this week.

FYI: as we've sort of discussed elsewhere, QuickType handles all of this pretty well.