Skip to content

Commit

Permalink
added limited support for conditional property values (#135)
Browse files Browse the repository at this point in the history
As mentioned in #129 we don't get fully resolved schemas based on the
data. Following the discussion in
sagold/json-schema-library#61, that appears to
be expected.

The workaround I implemented is to "fake" a deep schema resolution by
performing the shallow schema resolution on the direct children
properties of the schema (we only really care about the direct children
in this context).
  • Loading branch information
imolorhe authored Sep 6, 2024
1 parent bceace2 commit 917333e
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/nine-timers-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"codemirror-json-schema": patch
---

added limited support for conditional property values
14 changes: 13 additions & 1 deletion src/features/__tests__/__fixtures__/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export const testSchemaConditionalProperties = {
properties: {
type: {
type: "string",
enum: ["Test_1", "Test_2"],
enum: ["Test_1", "Test_2", "Test_3"],
},
props: {
type: "object",
Expand Down Expand Up @@ -181,5 +181,17 @@ export const testSchemaConditionalProperties = {
},
},
},
{
if: {
properties: {
type: { const: "Test_3" },
},
},
then: {
properties: {
props: { type: "string", enum: ["ace", "abu", "bay"] },
},
},
},
],
} as JSONSchema7;
18 changes: 18 additions & 0 deletions src/features/__tests__/json-completion.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,24 @@ describe.each([
],
schema: testSchemaConditionalProperties,
},
{
name: "autocomplete for a schema with conditional property values",
mode: MODES.JSON,
docs: ['{ "type": "Test_3", "props": "a|"'],
expectedResults: [
{
type: "string",
label: "ace",
apply: '"ace"',
},
{
type: "string",
label: "abu",
apply: '"abu"',
},
],
schema: testSchemaConditionalProperties,
},
// JSON5
{
name: "return bare property key when no quotes are used",
Expand Down
35 changes: 33 additions & 2 deletions src/features/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -837,19 +837,50 @@ export class JSONCompletion {
if (
!subSchema ||
subSchema.name === "UnknownPropertyError" ||
// TODO: Looking into why this is needed
subSchema.enum ||
subSchema.type === "undefined" ||
subSchema.type === "null"
) {
debug.log(
"xxx",
"no schema for pointer. Try parent pointer..",
pointer,
subSchema
);
pointer = pointer.replace(/\/[^/]*$/, "/");
subSchema = draft.getSchema({ pointer });
pointer = "/" ? "" : pointer; // root pointer should be empty ("/" is a JSON pointer for an empty string key)
subSchema = draft.getSchema({ pointer, data: data ?? undefined });
debug.log(
"xxx",
"subSchema for parent pointer",
subSchema,
pointer,
data
);
// resolve all direct child schemas
// TODO: This is a bit hacky, but it works for now
if (subSchema?.properties) {
Object.entries(subSchema.properties).forEach(([key, value]) => {
if (subSchema?.properties && typeof value === "object") {
subSchema.properties[key] = {
...value,
...draft.getSchema({
pointer: pointer + "/" + key,
data: data ?? undefined,
}),
};
}
});
debug.log("xxx", "direct children resolved", subSchema);
}
}

debug.log("xxx", "pointer..", JSON.stringify(pointer));

// For some reason, it returns undefined schema for the root pointer
// We use the root schema in that case as the relevant (sub)schema
if (!pointer || pointer === "/") {
if (!subSchema && (!pointer || pointer === "/")) {
subSchema = this.expandSchemaProperty(schema, schema) ?? schema;
}
// const subSchema = new Draft07(this.schema).getSchema(pointer);
Expand Down

0 comments on commit 917333e

Please sign in to comment.