Skip to content

Commit 917333e

Browse files
authored
added limited support for conditional property values (#135)
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).
1 parent bceace2 commit 917333e

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

.changeset/nine-timers-develop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"codemirror-json-schema": patch
3+
---
4+
5+
added limited support for conditional property values

src/features/__tests__/__fixtures__/schemas.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export const testSchemaConditionalProperties = {
140140
properties: {
141141
type: {
142142
type: "string",
143-
enum: ["Test_1", "Test_2"],
143+
enum: ["Test_1", "Test_2", "Test_3"],
144144
},
145145
props: {
146146
type: "object",
@@ -181,5 +181,17 @@ export const testSchemaConditionalProperties = {
181181
},
182182
},
183183
},
184+
{
185+
if: {
186+
properties: {
187+
type: { const: "Test_3" },
188+
},
189+
},
190+
then: {
191+
properties: {
192+
props: { type: "string", enum: ["ace", "abu", "bay"] },
193+
},
194+
},
195+
},
184196
],
185197
} as JSONSchema7;

src/features/__tests__/json-completion.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,24 @@ describe.each([
409409
],
410410
schema: testSchemaConditionalProperties,
411411
},
412+
{
413+
name: "autocomplete for a schema with conditional property values",
414+
mode: MODES.JSON,
415+
docs: ['{ "type": "Test_3", "props": "a|"'],
416+
expectedResults: [
417+
{
418+
type: "string",
419+
label: "ace",
420+
apply: '"ace"',
421+
},
422+
{
423+
type: "string",
424+
label: "abu",
425+
apply: '"abu"',
426+
},
427+
],
428+
schema: testSchemaConditionalProperties,
429+
},
412430
// JSON5
413431
{
414432
name: "return bare property key when no quotes are used",

src/features/completion.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,19 +837,50 @@ export class JSONCompletion {
837837
if (
838838
!subSchema ||
839839
subSchema.name === "UnknownPropertyError" ||
840+
// TODO: Looking into why this is needed
840841
subSchema.enum ||
841842
subSchema.type === "undefined" ||
842843
subSchema.type === "null"
843844
) {
845+
debug.log(
846+
"xxx",
847+
"no schema for pointer. Try parent pointer..",
848+
pointer,
849+
subSchema
850+
);
844851
pointer = pointer.replace(/\/[^/]*$/, "/");
845-
subSchema = draft.getSchema({ pointer });
852+
pointer = "/" ? "" : pointer; // root pointer should be empty ("/" is a JSON pointer for an empty string key)
853+
subSchema = draft.getSchema({ pointer, data: data ?? undefined });
854+
debug.log(
855+
"xxx",
856+
"subSchema for parent pointer",
857+
subSchema,
858+
pointer,
859+
data
860+
);
861+
// resolve all direct child schemas
862+
// TODO: This is a bit hacky, but it works for now
863+
if (subSchema?.properties) {
864+
Object.entries(subSchema.properties).forEach(([key, value]) => {
865+
if (subSchema?.properties && typeof value === "object") {
866+
subSchema.properties[key] = {
867+
...value,
868+
...draft.getSchema({
869+
pointer: pointer + "/" + key,
870+
data: data ?? undefined,
871+
}),
872+
};
873+
}
874+
});
875+
debug.log("xxx", "direct children resolved", subSchema);
876+
}
846877
}
847878

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

850881
// For some reason, it returns undefined schema for the root pointer
851882
// We use the root schema in that case as the relevant (sub)schema
852-
if (!pointer || pointer === "/") {
883+
if (!subSchema && (!pointer || pointer === "/")) {
853884
subSchema = this.expandSchemaProperty(schema, schema) ?? schema;
854885
}
855886
// const subSchema = new Draft07(this.schema).getSchema(pointer);

0 commit comments

Comments
 (0)