JSON Schemas for JSON Schema? #1233
Answered
by
waynesbrain
waynesbrain
asked this question in
Q&A
-
I am making an app that allows other developers to provide a JSON Schema for a type of object that they want. So, I find myself basically creating a schema for the const TObject = Type.Object({
type: Type.Literal("object"),
required: Type.Optional(
Type.Array(Type.String()),
),
properties: Type.Object({/* ... */})
}); And I'm wondering if I'm duplicating something that's already available from TypeBox or that someone else has done in an adjacent library? |
Beta Was this translation helpful? Give feedback.
Answered by
waynesbrain
Apr 22, 2025
Replies: 1 comment
-
Here's what I put together, it should cover most basic JSON schemas I think. If I have a problem with it, I'll update this: json-schema.tsimport { Static, Type } from "@sinclair/typebox";
const { Optional: Maybe } = Type;
export type TypeSchema = Static<typeof TypeSchema>;
export const TypeSchema = Type.Object(
{
$schema: Maybe(Type.String({ description: "The JSON Schema" })),
$id: Maybe(Type.String({ description: "Id for this schema" })),
title: Maybe(Type.String({ description: "Title of this schema" })),
description: Maybe(
Type.String({ description: "Description of this schema" }),
),
default: Maybe(Type.Any({ description: "Default value for this schema" })),
examples: Maybe(
Type.Any({ description: "Example values matching this schema" }),
),
readOnly: Maybe(
Type.Boolean({ description: "Optional annotation for readOnly" }),
),
writeOnly: Maybe(
Type.Boolean({ description: "Optional annotation for writeOnly" }),
),
},
{
additionalProperties: true,
},
);
// #region - Array
export type ArrayOptions = Static<typeof ArrayOptions>;
export const ArrayOptions = Type.Object({
minItems: Maybe(
Type.Number({ description: "The minimum number of items in this array" }),
),
maxItems: Maybe(
Type.Number({ description: "The maximum number of items in this array" }),
),
uniqueItems: Maybe(
Type.Boolean({ description: "Should this schema contain unique items" }),
),
contains: Maybe(
Type.Any({ description: "A schema for which some elements should match" }),
),
minContains: Maybe(
Type.Number({ description: "A minimum number of contains schema matches" }),
),
maxContains: Maybe(
Type.Number({ description: "A maximum number of contains schema matches" }),
),
});
export type TypeArray = Static<typeof TypeArray>;
export const TypeArray = Type.Composite([
TypeSchema,
ArrayOptions,
Type.Object({
type: Type.Literal("array"),
items: TypeSchema,
}),
]);
// #endregion
// #region - Boolean
export type TypeBoolean = Static<typeof TypeBoolean>;
export const TypeBoolean = Type.Composite([
TypeSchema,
Type.Object({
type: Type.Literal("boolean"),
}),
]);
// #endregion
// #region - Null
export type TypeNull = Static<typeof TypeNull>;
export const TypeNull = Type.Composite([
TypeSchema,
Type.Object({
type: Type.Literal("null"),
}),
]);
// #endregion
// #region - Number
export type NumberOptions = Static<typeof NumberOptions>;
export const NumberOptions = Type.Object({
exclusiveMaximum: Maybe(Type.Number()),
exclusiveMinimum: Maybe(Type.Number()),
maximum: Maybe(Type.Number()),
minimum: Maybe(Type.Number()),
multipleOf: Maybe(Type.Number()),
});
export type TypeNumber = Static<typeof TypeNumber>;
export const TypeNumber = Type.Composite([
TypeSchema,
NumberOptions,
Type.Object({
type: Type.Literal("number"),
}),
]);
// #endregion
// #region - Object
export type TypeProperties = Record<string, TypeSchema>;
export const TypeProperties = Type.Object(
{},
{
additionalProperties: TypeSchema,
},
);
export type TypeAdditionalProperties = Static<typeof TypeAdditionalProperties>;
export const TypeAdditionalProperties = Type.Union(
[Type.Boolean(), TypeSchema],
{ description: "Additional property constraints for this object" },
);
export type ObjectOptions = Static<typeof ObjectOptions>;
export const ObjectOptions = Type.Object({
additionalProperties: Maybe(TypeAdditionalProperties),
minProperties: Maybe(
Type.Number({
description: "The minimum number of properties allowed on this object",
}),
),
maxProperties: Maybe(
Type.Number({
description: "The maximum number of properties allowed on this object",
}),
),
});
export type TypeObject = Static<typeof TypeObject>;
export const TypeObject = Type.Composite([
TypeSchema,
ObjectOptions,
Type.Object({
type: Type.Literal("object"),
properties: TypeProperties,
required: Maybe(Type.Array(Type.String())),
}),
]);
// #endregion
// #region - String
export type StringOptions = Static<typeof StringOptions>;
export const StringOptions = Type.Object({
maxLength: Maybe(Type.Number({ description: "The maximum string length" })),
minLength: Maybe(Type.Number({ description: "The minimum string length" })),
pattern: Maybe(
Type.String({
description: "A regular expression pattern this string should match",
}),
),
format: Maybe(
Type.String({ description: "A format this string should match" }),
),
contentEncoding: Maybe(
Type.String({ description: "The content encoding for this string" }),
),
contentMediaType: Maybe(
Type.String({ description: "The content media type for this string" }),
),
});
export type TypeString = Static<typeof TypeString>;
export const TypeString = Type.Composite([
TypeSchema,
StringOptions,
Type.Object({
type: Type.Literal("string"),
}),
]);
// #endregion It covers the basics: |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
waynesbrain
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's what I put together, it should cover most basic JSON schemas I think. If I have a problem with it, I'll update this:
json-schema.ts