From 55f76570db4c6469df0a4104d5d0b97fe570e04d Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 23 Apr 2024 19:44:30 +0100 Subject: [PATCH 1/5] Improve comments in `render-object-table` Just documenting the current situation. --- .../partials/openapi/render-object-table.html | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html index 6faa21d9..2c59401d 100644 --- a/layouts/partials/openapi/render-object-table.html +++ b/layouts/partials/openapi/render-object-table.html @@ -9,11 +9,11 @@ * `properties`: optional dictionary of the properties to list, each given as: `property_name` : `property_data` - * `additionalProperties`: optional dictionary for properties with undefined - names, in the same format as `property_data` + * `additionalProperties`: an OpenAPI schema document for additional properties + on the object. * `patternProperties`: optional dictionary for properties with names adhering - to a regex pattern, in the same format as `property_data` + to a regex pattern. A map from regex pattern to OpenAPI schema document. * `required`: optional array containing the names of required properties. In some cases (such as response body specifications) this isn't used, and @@ -55,6 +55,15 @@ {{ else if (or .additionalProperties .patternProperties) }} + +{{/* +A special format of table for objects which only have additionalProperties or patternProperties. + +This is only ever used for top-level objects. Nested objects in this situation are just shown +as rows within their parent object, and don't get their own table. (They are filtered out in +resolve-additional-types.) +*/}} + {{ with $title }} {{ . }} @@ -113,7 +122,7 @@ {{ else if or (reflect.IsSlice .type) .oneOf }} {{/* It's legal to specify an array of types. - + There are two ways to do that: - Use an array of strings. - Use oneOf, with items having a schema. From 6f403f53b53061dcd3004999a3afcd402b34eeb5 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 23 Apr 2024 19:09:40 +0100 Subject: [PATCH 2/5] Pass `additionalProperties` and `patternProperties` into `render-object-table` Previously, we were stripping `additionalProperties` and `patternProperties` from all objects except top-level objects. Obviously, this was no good for objects where a nested property contains such properties. Fixing that (in `clean-object`) *ought* to be simple enough, except that it turned out we were relying on the fact that would give us an "empty" entry in the array of types-to-render-tables-for returned by `resolve-additional-types`. (Normally, we don't want an object that only has `additionalProperties` to have its own table, since we just embed it in the parent table.) So, we need to add more logic to `resolve-additional-types-inner` to suppress such tables. This commit doesn't change the rendered output at all (verified via `diff`): it's just preparation for what comes next. --- .../json-schema/resolve-additional-types.html | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index 157045b5..f210d0f7 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -29,6 +29,8 @@ * * * title * * properties + * * additionalProperties + * * patternProperties * * required * * enum * * anchor @@ -45,27 +47,31 @@ "schema" .schema "anchor_base" .anchor_base "name" (.name | default .schema.title | default "") + "top_level" true ) }} {{ return $res.objects }} /* * A helper for the resolve-additional-types partial. * - * Takes the same inputs as resolve-additional-types itself, except that `name` is mandatory. + * Takes the same inputs as resolve-additional-types itself, except: + * * `name` is mandatory. + * * `top_level`, if set, indicates that this is the top-level object. * * Returns a dict containing: * * * `objects`: The array of object schema definitions. * - * * `schema`: An updated copy of the `schema` input (eg, nested `allOf` - * entries are expanded, and an `anchor` may be added). If the input - * `schema` was itself an object, this will be the same as the first entry - * in `objects`. + * * `schema`: An updated copy of the `schema` input (eg, an `anchor` may be added). + * If the input `schema` was itself an object that we should create a table for, + * this will be the same as the first entry in `objects`. */ {{ define "partials/resolve-additional-types-inner" }} {{ $this_object := .schema }} {{ $anchor_base := .anchor_base }} {{ $name := .name }} + {{ $top_level := .top_level }} + {{ $all_objects := slice }} {{ if eq $this_object.type "object" }} @@ -126,12 +132,24 @@ {{ $this_object = merge $this_object (dict "properties" $updated_properties) }} {{ end }} - /* Finally, prepend the updated schema for the top-level object onto the $all_objects array */ - {{ $tmp := slice $this_object }} - {{ if $all_objects }} - {{ $tmp = $tmp | append $all_objects }} + /* We'll want to create a table for `$this_object` itself if either: + * + * - The object has some regular properties (not just patternProperties or additionalProperties), or: + * - It is the top-level object. (We use a special format of table for top-level objects that + * only have patternProperties or additionalProperties) + * + * In those cases, prepend the updated schema for the top-level object onto the $all_objects array. + * + * We think about this last so that we can take advantage of any updates to the schema that happened + * above (in particular, addition of `anchor` attributes). + */ + {{ if or $this_object.properties $top_level }} + {{ $tmp := slice $this_object }} + {{ if $all_objects }} + {{ $tmp = $tmp | append $all_objects }} + {{ end }} + {{ $all_objects = $tmp }} {{ end }} - {{ $all_objects = $tmp }} {{ end }} {{ if eq $this_object.type "array" }} @@ -193,8 +211,7 @@ * * Returns a dict containing: * * `objects`: The array of object schema definitions. - * * `schema`: An updated copy of the `schema` input (eg, nested `allOf` - * entries are expanded, and an `anchor` may be added). + * * `schema`: An updated copy of the `schema` input (eg, an `anchor` may be added). */ {{ define "partials/get-additional-objects" }} /* .name is the name of the object for logging purposes */ @@ -206,7 +223,7 @@ {{ errorf "Invalid call to partials/get-additional-objects: %s is not a map" $name .this_object }} {{ end }} - {{ $res := partial "resolve-additional-types-inner" (dict "schema" .this_object "anchor_base" .anchor_base "name" $name) }} + {{ $res := partial "resolve-additional-types-inner" (dict "schema" .this_object "anchor_base" .anchor_base "name" $name "top_level" false) }} {{ range $res.objects }} {{ $all_objects = $all_objects | append (partial "clean-object" .) }} {{ end }} @@ -221,5 +238,5 @@ * but with (for example) different examples will be considered different. */ {{ define "partials/clean-object" }} - {{ return (dict "title" .title "properties" .properties "required" .required "enum" .enum "anchor" .anchor) }} + {{ return (dict "title" .title "properties" .properties "additionalProperties" .additionalProperties "patternProperties" .patternProperties "required" .required "enum" .enum "anchor" .anchor) }} {{ end }} From 6aabf113b8698769dc9fcb83fa0d9ab913ea40f9 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 23 Apr 2024 19:17:22 +0100 Subject: [PATCH 3/5] Include `additionalProperties` data in object tables --- .../partials/openapi/render-object-table.html | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html index 2c59401d..b8903a4e 100644 --- a/layouts/partials/openapi/render-object-table.html +++ b/layouts/partials/openapi/render-object-table.html @@ -26,7 +26,6 @@ {{ $required := .required}} {{ if $properties }} - {{ with $title }} {{ . }} @@ -52,6 +51,28 @@ {{ end }} + {{/* + If the object has additional properties *as well as* regular properties, we add a special row to the table. + + Note that, per https://json-schema.org/draft/2020-12/json-schema-core#name-boolean-json-schemas, JSON schemas + can be a simple "true" or "false" as well as the more normal object. + + `additionalProperties: true` is pretty much the default for Matrix (it means: "you're allowed to include random + unspecced properties in your object"), so nothing to do here. + + `additionalProperties: false` means "you're not allowed to include any unspecced properties in your object". We + may want to consider how to display that; for now we just ignore it. + + TODO: support `patternProperties` here. + */}} + {{ if reflect.IsMap .additionalProperties }} + + + <Other properties> + {{ partial "partials/property-type" .additionalProperties }} + {{ partial "partials/property-description" (dict "property" .additionalProperties) }} + + {{ end }} {{ else if (or .additionalProperties .patternProperties) }} From b020b1d5c01b4b72a79b9978844025e5932bf8e0 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 23 Apr 2024 19:21:04 +0100 Subject: [PATCH 4/5] changelog --- changelogs/internal/newsfragments/1798.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/internal/newsfragments/1798.clarification diff --git a/changelogs/internal/newsfragments/1798.clarification b/changelogs/internal/newsfragments/1798.clarification new file mode 100644 index 00000000..5bd28a93 --- /dev/null +++ b/changelogs/internal/newsfragments/1798.clarification @@ -0,0 +1 @@ +Show information about "Additional Properties" in object tables. From f2ebb4003b4f0b9048c453510a85dfd1107bbf11 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 24 Apr 2024 11:07:06 +0100 Subject: [PATCH 5/5] Address review comments --- data/api/identity/v2_terms.yaml | 1 - layouts/partials/openapi/render-object-table.html | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/data/api/identity/v2_terms.yaml b/data/api/identity/v2_terms.yaml index d9eea90e..d7c231d4 100644 --- a/data/api/identity/v2_terms.yaml +++ b/data/api/identity/v2_terms.yaml @@ -52,7 +52,6 @@ paths: might be and could be "alpha", semantically versioned, or arbitrary. required: - version - # TODO: TravisR - Make this render additionalProperties: type: object title: Internationalised Policy diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html index b8903a4e..71bca884 100644 --- a/layouts/partials/openapi/render-object-table.html +++ b/layouts/partials/openapi/render-object-table.html @@ -9,11 +9,11 @@ * `properties`: optional dictionary of the properties to list, each given as: `property_name` : `property_data` - * `additionalProperties`: an OpenAPI schema document for additional properties - on the object. + * `additionalProperties`: a JSON Schema for additional properties on the + object. * `patternProperties`: optional dictionary for properties with names adhering - to a regex pattern. A map from regex pattern to OpenAPI schema document. + to a regex pattern. A map from regex pattern to JSON Schema. * `required`: optional array containing the names of required properties. In some cases (such as response body specifications) this isn't used, and @@ -69,7 +69,7 @@ <Other properties> - {{ partial "partials/property-type" .additionalProperties }} + {{ partial "partials/property-type" .additionalProperties | safeHTML }} {{ partial "partials/property-description" (dict "property" .additionalProperties) }} {{ end }}