Skip to content

Commit

Permalink
Handle unevaluatedProperties in JSON schema parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
juntyr committed Oct 7, 2024
1 parent eac4b47 commit 7d9ca30
Showing 1 changed file with 33 additions and 5 deletions.
38 changes: 33 additions & 5 deletions crates/numcodecs-python/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ fn parameters_from_schema(schema: &Schema) -> Parameters {
}
}

let mut additional = !matches!(schema.get("additionalProperties"), Some(Value::Bool(false)));
let mut additional = false;

extend_parameters_from_one_of_schema(schema, &mut parameters, &mut additional);

Expand All @@ -271,6 +271,15 @@ fn parameters_from_schema(schema: &Schema) -> Parameters {
// sort parameters by name and so that required parameters come first
parameters.sort_by_key(|p| (!p.required, p.name));

additional = match (
schema.get("additionalProperties"),
schema.get("unevaluatedProperties"),
) {
(Some(Value::Bool(false)), None) => additional,
(None | Some(Value::Bool(false)), Some(Value::Bool(false))) => false,
_ => true,
};

Parameters {
named: parameters,
additional,
Expand All @@ -284,13 +293,24 @@ fn extend_parameters_from_one_of_schema<'a>(
) {
// iterate over oneOf to handle top-level or flattened enums
if let Some(Value::Array(variants)) = schema.get("oneOf") {
// if any variant allows additional parameters, the top-level also
// allows additional parameters
*additional |= !matches!(schema.get("additionalProperties"), Some(Value::Bool(false)));

let mut variant_parameters = HashMap::new();

for (generation, schema) in variants.iter().enumerate() {
// if any variant allows additional parameters, the top-level also
// allows additional parameters
#[allow(clippy::unnested_or_patterns)]
if let Some(schema) = schema.as_object() {
*additional |= !matches!(
(
schema.get("additionalProperties"),
schema.get("unevaluatedProperties")
),
(Some(Value::Bool(false)), None)
| (None, Some(Value::Bool(false)))
| (Some(Value::Bool(false)), Some(Value::Bool(false)))
);
}

let required = match schema.get("required") {
Some(Value::Array(required)) => &**required,
_ => &[],
Expand Down Expand Up @@ -511,6 +531,14 @@ mod tests {

use super::*;

#[test]
fn schema() {
assert_eq!(
format!("{}", schema_for!(MyCodec).to_value()),
r#"{"type":"object","properties":{"param":{"type":["integer","null"],"format":"int32","description":"An optional integer value."}},"unevaluatedProperties":false,"oneOf":[{"type":"object","description":"Mode a.","properties":{"value":{"type":"boolean","description":"A boolean value."},"common":{"type":"string","description":"A common string value."},"mode":{"type":"string","const":"A"}},"required":["mode","value","common"]},{"type":"object","description":"Mode b.","properties":{"common":{"type":"string","description":"A common string value."},"mode":{"type":"string","const":"B"}},"required":["mode","common"]}],"description":"A codec that does something on encoding and decoding.","title":"MyCodec","$schema":"https://json-schema.org/draft/2020-12/schema"}"#
);
}

#[test]
fn docs() {
assert_eq!(
Expand Down

0 comments on commit 7d9ca30

Please sign in to comment.