The Constructor API provides a type-safe way to build JSON Schema using Go code. It supports all JSON Schema 2020-12 keywords and enables validation without compilation.
- Quick Start
- Basic Usage
- Core Types
- Validation Keywords
- Advanced Patterns
- Convenience Functions
- API Reference
import "github.com/kaptinlin/jsonschema"
// Create a user schema
userSchema := jsonschema.Object(
jsonschema.Prop("name", jsonschema.String(jsonschema.MinLength(1))),
jsonschema.Prop("age", jsonschema.Integer(jsonschema.Min(0))),
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Required("name", "email"),
)
// Validate data - no compilation step required
data := map[string]interface{}{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
}
result := userSchema.Validate(data)
if result.IsValid() {
fmt.Println("✅ Valid")
} else {
for field, err := range result.Errors {
fmt.Printf("❌ %s: %s\n", field, err.Message)
}
}The Constructor API uses function composition to build schemas:
// String with validation
nameSchema := jsonschema.String(
jsonschema.MinLength(1),
jsonschema.MaxLength(100),
jsonschema.Pattern("^[a-zA-Z\\s]+$"),
)
// Integer with constraints
ageSchema := jsonschema.Integer(
jsonschema.Min(0),
jsonschema.Max(150),
)
// Array of strings
tagsSchema := jsonschema.Array(
jsonschema.Items(jsonschema.String()),
jsonschema.MinItems(1),
jsonschema.UniqueItems(true),
)Objects are constructed using properties and keywords:
profileSchema := jsonschema.Object(
// Properties
jsonschema.Prop("username", jsonschema.String(
jsonschema.MinLength(3),
jsonschema.Pattern("^[a-zA-Z0-9_]+$"),
)),
jsonschema.Prop("profile", jsonschema.Object(
jsonschema.Prop("firstName", jsonschema.String()),
jsonschema.Prop("lastName", jsonschema.String()),
)),
jsonschema.Prop("settings", jsonschema.Object(
jsonschema.Prop("theme", jsonschema.Enum("light", "dark", "auto")),
jsonschema.Prop("notifications", jsonschema.Boolean()),
)),
// Object constraints
jsonschema.Required("username"),
jsonschema.AdditionalProps(false),
)// String schema
jsonschema.String(keywords...) // String with validation keywords
jsonschema.Integer(keywords...) // Integer with constraints
jsonschema.Number(keywords...) // Number with constraints
jsonschema.Boolean() // Boolean type
jsonschema.Null() // Null type
jsonschema.Array(keywords...) // Array with validation
jsonschema.Object(props...) // Object with properties
jsonschema.Any() // Any type (no restrictions)// Constant values
jsonschema.Const("fixed-value") // Exact value match
jsonschema.Enum("red", "green", "blue") // One of specified values// Logical combinations
jsonschema.OneOf(schemas...) // Exactly one schema must match
jsonschema.AnyOf(schemas...) // At least one schema must match
jsonschema.AllOf(schemas...) // All schemas must match
jsonschema.Not(schema) // Schema must not match// Schema references
jsonschema.Ref("#/definitions/User") // Reference to another schemajsonschema.String(
jsonschema.MinLength(5), // Minimum length
jsonschema.MaxLength(100), // Maximum length
jsonschema.Pattern("^[a-zA-Z]+$"), // Regular expression
jsonschema.Format("email"), // Format validation
)jsonschema.Number(
jsonschema.Min(0), // Minimum value (inclusive)
jsonschema.Max(100), // Maximum value (inclusive)
jsonschema.ExclusiveMin(0), // Minimum value (exclusive)
jsonschema.ExclusiveMax(100), // Maximum value (exclusive)
jsonschema.MultipleOf(2.5), // Must be multiple of value
)jsonschema.Array(
jsonschema.Items(itemSchema), // Schema for array items
jsonschema.MinItems(1), // Minimum number of items
jsonschema.MaxItems(10), // Maximum number of items
jsonschema.UniqueItems(true), // Items must be unique
jsonschema.Contains(schema), // Array must contain item matching schema
jsonschema.MinContains(2), // Minimum matching contains items
jsonschema.MaxContains(5), // Maximum matching contains items
jsonschema.PrefixItems(schemas...), // Schemas for array prefix
jsonschema.UnevaluatedItems(schema), // Schema for unevaluated items
)jsonschema.Object(
// Property constraints
jsonschema.Required("field1", "field2"), // Required properties
jsonschema.MinProps(1), // Minimum number of properties
jsonschema.MaxProps(10), // Maximum number of properties
// Additional properties
jsonschema.AdditionalProps(false), // Disallow additional properties
jsonschema.AdditionalPropsSchema(schema), // Schema for additional properties
// Pattern properties
jsonschema.PatternProps(map[string]*Schema{
"^str_": jsonschema.String(),
"^num_": jsonschema.Number(),
}),
// Property names
jsonschema.PropertyNames(
jsonschema.String(jsonschema.Pattern("^[a-zA-Z_]+$")),
),
// Dependencies
jsonschema.DependentRequired(map[string][]string{
"credit_card": {"billing_address"},
}),
jsonschema.DependentSchemas(map[string]*Schema{
"credit_card": jsonschema.Object(
jsonschema.Required("billing_address"),
),
}),
// Unevaluated properties
jsonschema.UnevaluatedProps(schema),
)// Metadata (doesn't affect validation)
jsonschema.String(
jsonschema.Title("User Name"), // Human-readable title
jsonschema.Description("User's login name"), // Detailed description
jsonschema.Default("guest"), // Default value
jsonschema.Examples("admin", "user"), // Example values
jsonschema.Deprecated(true), // Mark as deprecated
jsonschema.ReadOnly(true), // Read-only field
jsonschema.WriteOnly(true), // Write-only field
)The Constructor API integrates with the compiler system for schema registration and reuse:
// Create a reusable schema with ID
userSchema := jsonschema.Object(
jsonschema.ID("https://example.com/schemas/user"),
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("name", jsonschema.String(jsonschema.MinLength(1))),
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Required("id", "name", "email"),
)
// Register schema with compiler
compiler := jsonschema.NewCompiler()
compiler.SetSchema("https://example.com/schemas/user", userSchema)// Reference registered schema in JSON
profileJSON := `{
"type": "object",
"properties": {
"user": {"$ref": "https://example.com/schemas/user"},
"bio": {"type": "string"},
"lastLogin": {"type": "string", "format": "date-time"}
},
"required": ["user"]
}`
// Compile schema that references registered constructor schema
profileSchema, err := compiler.Compile([]byte(profileJSON))
if err != nil {
log.Fatal(err)
}
// Validate data against composed schema
data := map[string]interface{}{
"user": map[string]interface{}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Alice",
"email": "alice@example.com",
},
"bio": "Software Developer",
"lastLogin": "2023-12-01T10:30:00Z",
}
result := profileSchema.Validate(data)// Schema with internal definitions
apiSchema := jsonschema.Object(
jsonschema.Prop("users", jsonschema.Array(
jsonschema.Items(jsonschema.Ref("#/$defs/User")),
)),
jsonschema.Prop("pagination", jsonschema.Ref("#/$defs/Pagination")),
jsonschema.Defs(map[string]*Schema{
"User": jsonschema.Object(
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("name", jsonschema.String()),
jsonschema.Required("id", "name"),
),
"Pagination": jsonschema.Object(
jsonschema.Prop("page", jsonschema.PositiveInt()),
jsonschema.Prop("size", jsonschema.Integer(
jsonschema.Min(1),
jsonschema.Max(100),
)),
jsonschema.Prop("total", jsonschema.NonNegativeInt()),
jsonschema.Required("page", "size", "total"),
),
}),
jsonschema.Required("users", "pagination"),
)Use If/Then/Else for conditional validation:
// If user type is "premium", then premium features are required
conditionalSchema := jsonschema.If(
jsonschema.Object(
jsonschema.Prop("type", jsonschema.Const("premium")),
),
).Then(
jsonschema.Object(
jsonschema.Required("premium_features"),
),
).Else(
jsonschema.Object(
jsonschema.Prop("premium_features", jsonschema.Not(jsonschema.Any())),
),
)blogPostSchema := jsonschema.Object(
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("title", jsonschema.String(
jsonschema.MinLength(1),
jsonschema.MaxLength(200),
)),
jsonschema.Prop("author", jsonschema.Object(
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("name", jsonschema.String()),
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Required("id", "name", "email"),
)),
jsonschema.Prop("tags", jsonschema.Array(
jsonschema.Items(jsonschema.String(
jsonschema.MinLength(1),
jsonschema.MaxLength(50),
)),
jsonschema.UniqueItems(true),
jsonschema.MinItems(1),
jsonschema.MaxItems(10),
)),
jsonschema.Prop("comments", jsonschema.Array(
jsonschema.Items(jsonschema.Object(
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("content", jsonschema.String(jsonschema.MinLength(1))),
jsonschema.Prop("author_name", jsonschema.String()),
jsonschema.Prop("created_at", jsonschema.DateTime()),
jsonschema.Required("id", "content", "author_name", "created_at"),
)),
)),
jsonschema.Required("id", "title", "author", "tags"),
)// OneOf: User can authenticate with email OR username
authSchema := jsonschema.OneOf(
jsonschema.Object(
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Prop("password", jsonschema.String()),
jsonschema.Required("email", "password"),
jsonschema.AdditionalProps(false),
),
jsonschema.Object(
jsonschema.Prop("username", jsonschema.String()),
jsonschema.Prop("password", jsonschema.String()),
jsonschema.Required("username", "password"),
jsonschema.AdditionalProps(false),
),
)
// AnyOf: Contact info can be email, phone, or both
contactSchema := jsonschema.AnyOf(
jsonschema.Object(
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Required("email"),
),
jsonschema.Object(
jsonschema.Prop("phone", jsonschema.String()),
jsonschema.Required("phone"),
),
)
// AllOf: Combine multiple constraints
strictUserSchema := jsonschema.AllOf(
jsonschema.Object(
jsonschema.Prop("name", jsonschema.String()),
jsonschema.Required("name"),
),
jsonschema.Object(
jsonschema.MinProps(1),
jsonschema.MaxProps(10),
),
)Predefined schemas for common formats and patterns:
// String formats
jsonschema.Email() // Email format
jsonschema.DateTime() // ISO 8601 date-time
jsonschema.Date() // ISO 8601 date
jsonschema.Time() // ISO 8601 time
jsonschema.URI() // URI format
jsonschema.URIRef() // URI reference
jsonschema.UUID() // UUID format
jsonschema.Hostname() // Hostname format
jsonschema.IPv4() // IPv4 address
jsonschema.IPv6() // IPv6 address
jsonschema.IdnEmail() // Internationalized email
jsonschema.IdnHostname() // Internationalized hostname
jsonschema.IRI() // IRI format
jsonschema.IRIRef() // IRI reference
jsonschema.URITemplate() // URI template
jsonschema.JSONPointer() // JSON Pointer
jsonschema.RelativeJSONPointer() // Relative JSON Pointer
jsonschema.Duration() // Duration format
jsonschema.Regex() // Regular expression// Integer constraints
jsonschema.PositiveInt() // minimum: 1
jsonschema.NonNegativeInt() // minimum: 0
jsonschema.NegativeInt() // maximum: -1
jsonschema.NonPositiveInt() // maximum: 0apiSchema := jsonschema.Object(
jsonschema.Prop("id", jsonschema.UUID()),
jsonschema.Prop("created_at", jsonschema.DateTime()),
jsonschema.Prop("website", jsonschema.URI()),
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Prop("count", jsonschema.NonNegativeInt()),
jsonschema.Prop("score", jsonschema.PositiveInt()),
)Creates an object schema. Accepts properties and object keywords.
schema := jsonschema.Object(
jsonschema.Prop("name", jsonschema.String()),
jsonschema.Required("name"),
)Creates a string schema with validation keywords.
schema := jsonschema.String(
jsonschema.MinLength(1),
jsonschema.Format("email"),
)Creates an integer schema with number keywords.
schema := jsonschema.Integer(
jsonschema.Min(0),
jsonschema.Max(100),
)Creates a number schema with number keywords.
schema := jsonschema.Number(
jsonschema.Min(0.0),
jsonschema.MultipleOf(0.5),
)Creates a boolean schema.
schema := jsonschema.Boolean()Creates a null schema.
schema := jsonschema.Null()Creates an array schema with array keywords.
schema := jsonschema.Array(
jsonschema.Items(jsonschema.String()),
jsonschema.MinItems(1),
)Creates a schema that accepts any type.
schema := jsonschema.Any()Creates a property definition for objects.
prop := jsonschema.Prop("username", jsonschema.String())Creates a constant value schema.
schema := jsonschema.Const("fixed-value")Creates an enumeration schema.
schema := jsonschema.Enum("red", "green", "blue")Creates a oneOf composition schema.
schema := jsonschema.OneOf(
jsonschema.String(),
jsonschema.Integer(),
)Creates an anyOf composition schema.
schema := jsonschema.AnyOf(
jsonschema.String(jsonschema.MinLength(5)),
jsonschema.Integer(jsonschema.Min(0)),
)Creates an allOf composition schema.
schema := jsonschema.AllOf(
jsonschema.Object(jsonschema.Prop("name", jsonschema.String())),
jsonschema.Object(jsonschema.MinProps(1)),
)Creates a negation schema.
schema := jsonschema.Not(jsonschema.String())Creates a reference schema.
schema := jsonschema.Ref("#/definitions/User")Creates a conditional schema.
conditionalSchema := jsonschema.If(
jsonschema.Object(
jsonschema.Prop("type", jsonschema.Const("premium")),
),
).Then(
jsonschema.Object(
jsonschema.Required("premium_features"),
),
).Else(
jsonschema.Object(
jsonschema.Required("basic_features"),
),
)MinLength(min int) Keyword- Sets minLengthMaxLength(max int) Keyword- Sets maxLengthPattern(pattern string) Keyword- Sets patternFormat(format string) Keyword- Sets format
Min(min float64) Keyword- Sets minimumMax(max float64) Keyword- Sets maximumExclusiveMin(min float64) Keyword- Sets exclusiveMinimumExclusiveMax(max float64) Keyword- Sets exclusiveMaximumMultipleOf(multiple float64) Keyword- Sets multipleOf
Items(schema *Schema) Keyword- Sets itemsMinItems(min int) Keyword- Sets minItemsMaxItems(max int) Keyword- Sets maxItemsUniqueItems(unique bool) Keyword- Sets uniqueItemsContains(schema *Schema) Keyword- Sets containsMinContains(min int) Keyword- Sets minContainsMaxContains(max int) Keyword- Sets maxContainsPrefixItems(schemas ...*Schema) Keyword- Sets prefixItemsUnevaluatedItems(schema *Schema) Keyword- Sets unevaluatedItems
Required(fields ...string) Keyword- Sets requiredAdditionalProps(allowed bool) Keyword- Sets additionalProperties (boolean)AdditionalPropsSchema(schema *Schema) Keyword- Sets additionalProperties (schema)MinProps(min int) Keyword- Sets minPropertiesMaxProps(max int) Keyword- Sets maxPropertiesPatternProps(patterns map[string]*Schema) Keyword- Sets patternPropertiesPropertyNames(schema *Schema) Keyword- Sets propertyNamesUnevaluatedProps(schema *Schema) Keyword- Sets unevaluatedPropertiesDependentRequired(dependencies map[string][]string) Keyword- Sets dependentRequiredDependentSchemas(dependencies map[string]*Schema) Keyword- Sets dependentSchemas
Title(title string) Keyword- Sets titleDescription(desc string) Keyword- Sets descriptionDefault(value interface{}) Keyword- Sets defaultExamples(examples ...interface{}) Keyword- Sets examplesDeprecated(deprecated bool) Keyword- Sets deprecatedReadOnly(readOnly bool) Keyword- Sets readOnlyWriteOnly(writeOnly bool) Keyword- Sets writeOnly
ContentEncoding(encoding string) Keyword- Sets contentEncodingContentMediaType(mediaType string) Keyword- Sets contentMediaTypeContentSchema(schema *Schema) Keyword- Sets contentSchema
ID(id string) Keyword- Sets $idSchemaURI(schemaURI string) Keyword- Sets $schemaAnchor(anchor string) Keyword- Sets $anchorDynamicAnchor(anchor string) Keyword- Sets $dynamicAnchorDefs(defs map[string]*Schema) Keyword- Sets $defs
const (
FormatEmail = "email"
FormatDateTime = "date-time"
FormatDate = "date"
FormatTime = "time"
FormatURI = "uri"
FormatURIRef = "uri-reference"
FormatUUID = "uuid"
FormatHostname = "hostname"
FormatIPv4 = "ipv4"
FormatIPv6 = "ipv6"
FormatRegex = "regex"
FormatIdnEmail = "idn-email"
FormatIdnHostname = "idn-hostname"
FormatIRI = "iri"
FormatIRIRef = "iri-reference"
FormatURITemplate = "uri-template"
FormatJSONPointer = "json-pointer"
FormatRelativeJSONPointer = "relative-json-pointer"
FormatDuration = "duration"
)The Constructor API offers several characteristics compared to JSON string compilation:
- Type Safety: Compile-time checking prevents invalid keyword usage
- Direct Use: Schemas can be used without parsing step
- Composability: Supports building complex schemas from reusable components
- Code Structure: Schema structure corresponds to code structure
- Maintainability: Changes and refactoring can be handled through IDE tools
- Specification Coverage: Supports all JSON Schema 2020-12 keywords
The Constructor API works alongside the existing JSON compilation API:
// Constructor API
constructedSchema := jsonschema.Object(
jsonschema.Prop("name", jsonschema.String()),
)
// JSON compilation API
compiler := jsonschema.NewCompiler()
jsonSchema, _ := compiler.Compile([]byte(`{
"type": "object",
"properties": {
"name": {"type": "string"}
}
}`))
// Both schemas function identically
data := map[string]interface{}{"name": "test"}
result1 := constructedSchema.Validate(data)
result2 := jsonSchema.Validate(data)This compatibility enables adoption and allows using both approaches in the same application.