Add Support for Json schema examples (#4447)

fix #3946
This commit is contained in:
Timothee Guerin 2024-09-16 09:36:15 -07:00 коммит произвёл GitHub
Родитель 0108755871
Коммит d0666e643e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 68 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,7 @@
---
changeKind: feature
packages:
- "@typespec/json-schema"
---
Example set with `@example` decorator will populate the schema `examples` property

Просмотреть файл

@ -21,6 +21,7 @@ import {
getDeprecated,
getDirectoryPath,
getDoc,
getExamples,
getFormat,
getMaxItems,
getMaxLength,
@ -37,6 +38,7 @@ import {
isNullType,
isType,
joinPaths,
serializeValueAsJson,
} from "@typespec/compiler";
import {
ArrayBuilder,
@ -538,6 +540,20 @@ export class JsonSchemaEmitter extends TypeEmitter<Record<string, any>, JSONSche
}
}
#applySchemaExamples(
type: Model | Scalar | Union | Enum | ModelProperty,
target: ObjectBuilder<unknown>
) {
const program = this.emitter.getProgram();
const examples = getExamples(program, type);
if (examples.length > 0) {
target.set(
"examples",
examples.map((x) => serializeValueAsJson(program, x.value, type))
);
}
}
#applyConstraints(
type: Scalar | Model | ModelProperty | Union | UnionVariant | Enum,
schema: ObjectBuilder<unknown>
@ -557,7 +573,9 @@ export class JsonSchemaEmitter extends TypeEmitter<Record<string, any>, JSONSche
schema.set(key, ref.value);
}
};
if (type.kind !== "UnionVariant") {
this.#applySchemaExamples(type, schema);
}
applyConstraint(getMinLength, "minLength");
applyConstraint(getMaxLength, "maxLength");
applyConstraint(getMinValue, "minimum");

Просмотреть файл

@ -0,0 +1,42 @@
import { expect, it } from "vitest";
import { emitSchema } from "./utils.js";
it("apply example on model", async () => {
const schemas = await emitSchema(
`
@example(#{name: "John"})
model Test { name: string }
`
);
expect(schemas["Test.json"].examples).toEqual([{ name: "John" }]);
});
it("apply multiple example on model", async () => {
const schemas = await emitSchema(
`
@example(#{name: "Jane"})
@example(#{name: "John"})
model Test { name: string }
`
);
expect(schemas["Test.json"].examples).toEqual([{ name: "John" }, { name: "Jane" }]);
});
it("apply example on property", async () => {
const schemas = await emitSchema(
`
model Test { @example("John") name: string }
`
);
expect(schemas["Test.json"].properties.name.examples).toEqual(["John"]);
});
it("serialize the examples with their json encoding", async () => {
const schemas = await emitSchema(
`
@example(#{dob: plainDate.fromISO("2021-01-01")})
model Test { dob: plainDate }
`
);
expect(schemas["Test.json"].examples).toEqual([{ dob: "2021-01-01" }]);
});