The ObjectSchema provides comprehensive validation for object/map values with support for property schemas, required fields, additional properties control, and more.
import "github.com/nyxstack/schema"
// Basic object schema
userSchema := schema.Object()
// Using Property method
userSchema := schema.Object().
Property("name", schema.String().Required()).
Property("email", schema.String().Email().Required()).
Property("age", schema.Int().Min(0).Optional())
// Using Shape (concise syntax)
userSchema := schema.Shape{
"name": schema.String().Required(),
"email": schema.String().Email().Required(),
"age": schema.Int().Min(0).Optional(),
}.AsObject()Marks the object as required (cannot be nil or omitted).
schema.Object().Required()
schema.Object().Required("Object is required")
schema.Object().Required(i18n.S("object is required"))Marks the object as optional (can be nil or omitted).
schema.Object().Optional()Allows the object value to be explicitly null.
schema.Object().Nullable()Sets a default value when the input is nil.
schema.Object().Default(map[string]interface{}{
"status": "active",
})Adds a property with automatic required/optional detection from the schema.
schema.Object().
Property("name", schema.String().Required()). // Required
Property("age", schema.Int().Optional()) // OptionalExplicitly adds a required property.
schema.Object().
RequiredProperty("id", schema.Int()).
RequiredProperty("name", schema.String())Explicitly adds an optional property.
schema.Object().
OptionalProperty("nickname", schema.String()).
OptionalProperty("avatar", schema.String().URL())Sets the minimum number of properties.
schema.Object().MinProperties(1)
schema.Object().MinProperties(2, "Must have at least 2 properties")
schema.Object().MinProperties(1, i18n.F("must have at least %d properties", 1))Sets the maximum number of properties.
schema.Object().MaxProperties(10)
schema.Object().MaxProperties(5, "Cannot exceed 5 properties")Sets both minimum and maximum property counts.
schema.Object().PropertyRange(2, 10)Controls whether additional properties beyond defined ones are allowed.
// Disallow additional properties
schema.Object().AdditionalProperties(false)
// Allow additional properties
schema.Object().AdditionalProperties(true)
// With custom error
schema.Object().AdditionalProperties(false, "Extra fields not allowed")Disallows additional properties (default behavior).
schema.Object().
Property("name", schema.String().Required()).
Strict() // Only "name" is allowedAllows additional properties.
schema.Object().
Property("name", schema.String().Required()).
Passthrough() // Additional properties allowedSets a title for documentation and JSON Schema generation.
schema.Object().Title("User Profile")Sets a description for documentation and JSON Schema generation.
schema.Object().Description("User profile information")userSchema := schema.Object().
Property("name", schema.String().Required()).
Property("email", schema.String().Email().Required()).
Property("age", schema.Int().Min(0).Optional())
ctx := schema.DefaultValidationContext()
result := userSchema.Parse(map[string]interface{}{
"name": "Alice",
"email": "alice@example.com",
"age": 30,
}, ctx)
if result.Valid {
fmt.Printf("Valid user: %v\n", result.Value)
}userSchema := schema.Shape{
"username": schema.String().MinLength(3).Required(),
"email": schema.String().Email().Required(),
"age": schema.Int().Min(18).Optional(),
}.AsObject()addressSchema := schema.Shape{
"street": schema.String().Required(),
"city": schema.String().Required(),
"zip": schema.String().Pattern("^\\d{5}$").Required(),
}.AsObject()
userSchema := schema.Object().
Property("name", schema.String().Required()).
Property("address", addressSchema.Required())
result := userSchema.Parse(map[string]interface{}{
"name": "Bob",
"address": map[string]interface{}{
"street": "123 Main St",
"city": "Springfield",
"zip": "12345",
},
}, ctx)// Strict: Only defined properties allowed (default)
strictSchema := schema.Object().
Property("name", schema.String().Required()).
Strict()
// Invalid - "age" not defined
strictSchema.Parse(map[string]interface{}{
"name": "Alice",
"age": 30, // Error: additional property not allowed
}, ctx)
// Passthrough: Additional properties allowed
passthroughSchema := schema.Object().
Property("name", schema.String().Required()).
Passthrough()
// Valid - "age" is passed through
passthroughSchema.Parse(map[string]interface{}{
"name": "Alice",
"age": 30, // OK
}, ctx)schema := schema.Object().
Property("id", schema.Int().Required()). // Required
Property("name", schema.String().Required()). // Required
Property("email", schema.String().Optional()). // Optional
Property("phone", schema.String().Optional()) // Optional
// Valid - optional fields can be omitted
schema.Parse(map[string]interface{}{
"id": 1,
"name": "Alice",
}, ctx)metadataSchema := schema.Object().
MinProperties(1, "At least one property required").
MaxProperties(10, "Maximum 10 properties allowed").
Passthrough()
result := metadataSchema.Parse(map[string]interface{}{
"key1": "value1",
"key2": "value2",
}, ctx)orderSchema := schema.Object().
Property("orderId", schema.Int().Required()).
Property("customer", schema.Object().
Property("id", schema.Int().Required()).
Property("name", schema.String().Required()).
Property("email", schema.String().Email().Required())).
Property("items", schema.Array(
schema.Object().
Property("productId", schema.Int().Required()).
Property("quantity", schema.Int().Min(1).Required()).
Property("price", schema.Number().Min(0).Required()),
).MinItems(1)).
Property("total", schema.Number().Min(0).Required())
result := orderSchema.Parse(map[string]interface{}{
"orderId": 12345,
"customer": map[string]interface{}{
"id": 101,
"name": "Alice",
"email": "alice@example.com",
},
"items": []map[string]interface{}{
{"productId": 1, "quantity": 2, "price": 19.99},
{"productId": 2, "quantity": 1, "price": 49.99},
},
"total": 89.97,
}, ctx)createUserRequest := schema.Object().
Property("user", schema.Object().
Property("username", schema.String().MinLength(3).Required()).
Property("email", schema.String().Email().Required()).
Property("password", schema.String().MinLength(8).Required())).
AdditionalProperties(false)
result := createUserRequest.Parse(requestData, ctx)userSchema := schema.Object().
Property("name", schema.String().
MinLength(2, i18n.F("name must be at least %d characters", 2)).
Required(i18n.S("name is required"))).
Property("age", schema.Int().
Min(18, i18n.F("must be at least %d years old", 18)).
Required(i18n.S("age is required"))).
AdditionalProperties(false, i18n.S("additional properties not allowed"))
result := userSchema.Parse(data, ctx)configSchema := schema.Object().
Property("port", schema.Int().Min(1024).Max(65535).Default(8080)).
Property("host", schema.String().Default("localhost")).
Property("debug", schema.Bool().Default(false)).
Property("timeout", schema.Int().Min(0).Default(30)).
Passthrough()
result := configSchema.Parse(nil, ctx) // Uses all defaultsupdateSchema := schema.Object().
OptionalProperty("name", schema.String().MinLength(1)).
OptionalProperty("email", schema.String().Email()).
OptionalProperty("age", schema.Int().Min(0)).
MinProperties(1, "At least one field must be provided").
AdditionalProperties(false)
result := updateSchema.Parse(map[string]interface{}{
"email": "newemail@example.com",
}, ctx) // Valid - only updating emailresult := schema.Parse(data, ctx)
if !result.Valid {
for _, err := range result.Errors {
fmt.Printf("Path: %v\n", err.Path)
fmt.Printf("Value: %v\n", err.Value)
fmt.Printf("Message: %s\n", err.Message)
fmt.Printf("Code: %s\n", err.Code)
}
}Property errors include the property name in the path:
Path: name
Message: value must be at least 2 characters long
Path: address.zip
Message: value format is invalid
All error messages support i18n through the github.com/nyxstack/i18n package:
schema.Object().
Property("name", schema.String().Required(i18n.S("name is required"))).
MinProperties(1, i18n.F("must have at least %d properties", 1)).
AdditionalProperties(false, i18n.S("additional properties not allowed"))schema := schema.Object().
Title("User").
Description("User profile").
Property("id", schema.Int().Required()).
Property("name", schema.String().Required()).
Property("email", schema.String().Email().Optional()).
AdditionalProperties(false)
jsonSchema := schema.JSON()
// Outputs:
// {
// "type": "object",
// "properties": {
// "id": {"type": "integer"},
// "name": {"type": "string"},
// "email": {"type": "string", "format": "email"}
// },
// "required": ["id", "name"],
// "additionalProperties": false,
// "title": "User",
// "description": "User profile"
// }- Record Schema - For dynamic key-value maps
- Array Schema - For arrays of objects
- String Schema - For object properties
- Shape - Concise object syntax