jobj
is a Go package that provides a flexible way to create and manage JSON schema definitions. It offers an API for defining JSON data structures for generating JSON schemas specifically in the context of requesting structured JSON objects from large language models (LLMs). It also provides limited support for XML schemas
If you want to create a json schema from a struct, you can use packages like jsonschema that use reflection and field tags. However, using tags creates ergonomic challenges for the programmer, specifically if you ever require a long description on a field. jobj
is designed to get around this ergonomic issue and to create json object tooling for LLM development, which requires only a subset of the json schema.
This package implements a focused subset of the JSON Schema Draft-07 specification, prioritizing the elements most useful for LLM interactions:
- Core schema structure with
$schema
,definitions
, and$ref
- Object type definitions with properties and typing
- Required/optional field specification
- Property descriptions
- Basic property types: string, number, integer, boolean
- Nested objects and arrays
- Enum-like constraints using
anyOf
- Default value specification
additionalProperties
field control
- Format validation (except for custom
JsonDateTime
type) - Regular expression pattern validation
- Numeric constraints (minimum, maximum, etc.)
- String constraints (minLength, maxLength, etc.)
- Array constraints (minItems, maxItems, etc.)
- Schema composition (allOf, oneOf, not)
- External schema references
- Conditional schemas (if-then-else)
- Clean API for schema definition with chainable methods
- Custom JSON date/time handling with
JsonDateTime
type supporting multiple formats - Support for nested objects and arrays
- Enum-like field constraints using
AnyOf
- Required/optional field specification
- XML schema generation (limited subset)
- Generate JSON schemas from Go function signatures via the
funcschema
subpackage - Validation against Go structs
- Struct tag parsing for automated schema generation
go get github.com/mhpenta/jobj
package main
import "github.com/mhpenta/jobj"
type HeadlinesResponse struct {
jobj.Schema
}
func NewHeadlineResponse() *HeadlinesResponse {
h := &HeadlinesResponse{}
h.Name = "HeadlinesResponse"
h.Description = "Response schema for press release headline extraction"
h.Fields = []*jobj.Field{
jobj.Text("headline").
Desc("The exact headline from the press release (in proper case)").
Required(),
jobj.Text("headline_without_company_name").
Desc("The headline from the press release modified to remove the company name (in proper case)").
Required(),
jobj.Float("confidence").
Desc("Confidence in the headlines extracted").
Required(),
}
return h
}
// Generate JSON schema
schema := NewHeadlineResponse()
schemaJSON := schema.GetSchemaString()
fmt.Println(schemaJSON)
Prints:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"HeadlinesResponse": {
"additionalProperties": false,
"properties": {
"confidence": {
"description": "Confidence in the headlines extracted",
"type": "number"
},
"headline": {
"description": "The exact headline from the press release (in proper case)",
"type": "string"
},
"headline_without_company_name": {
"description": "The headline from the press release modified to remove the company name (in proper case)",
"type": "string"
}
},
"required": [
"headline",
"headline_without_company_name",
"confidence"
],
"type": "object"
}
},
"$ref": "#/definitions/HeadlinesResponse"
}
The package supports various field types:
Text(name string)
- String fieldsBool(name string)
- Boolean fieldsFloat(name string)
- Floating-point numbersInt(name string)
- Integer fieldsDate(name string)
- Date fields using the custom JsonDateTime typeArray(name string, fields []*Field)
- Array of objectsObject(name string, fields []*Field)
- Nested object structuresAnyOf(name string, enums []ConstDescription)
- Enumerated values
Fields can be customized using chainable modifiers:
jobj.Text("field").
Desc("Field description"). // Add description
Required(). // Mark as required (adds field name to schema's "required" array)
Optional(). // Mark as optional (removes field from "required" array)
Type("custom_type"). // Set custom type
SetValue("default") // Set default value
The package includes a custom JsonDateTime
type for handling dates:
type Document struct {
PublishDate JsonDateTime `json:"publish_date"`
}
The JsonDateTime
type offers robust date parsing that handles multiple formats, including:
- ISO 8601/RFC3339 (2006-01-02T15:04:05Z)
- RFC3339 with timezone (2006-01-02T15:04:05-07:00)
- Simple date format (2006-01-02)
- Various other common time formats
The funcschema
subpackage allows you to automatically generate JSON schemas from Go function signatures. This is particularly useful for creating LLM tools that require parameter schemas.
// Define your tool's parameter struct
type SearchToolParams struct {
ID int `desc:"ID of item to search" required:"true" `
Query string `desc:"Query to search for, e.g., xyz" required:"true"`
}
// Create a function that uses the parameters
func (t *SearchTool) ExecuteSearch(ctx context.Context, params *SearchToolParams) (*ToolResult, error) {
// Implementation...
}
// Generate a JSON schema from the function
func (t *SearchTool) Parameters() map[string]interface{} {
schema, err := funcschema.SafeSchemaFromFunc(t.ExecuteSearch)
if err != nil {
// Handle error
}
return schema
}
// Called by the agent
func (t *SearchTool) Execute(ctx context.Context, params json.RawMessage) (*tools.ToolResult, error) {
var paramsStruct *SearchToolParams
if err := json.Unmarshal(params, paramsStruct); err != nil {
// Handle error
}
searchResult, err := t.ExecuteSearch(ctx, paramsStruct)
if err != nil {
// Handle error
}
return searchResult, nil
}
The funcschema
subpackage's schema for tool use looks like:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"SearchToolParams": {
"additionalProperties": false,
"properties": {
"ID": {
"description": "ID of item to search",
"type": "integer"
},
"Query": {
"description": "Query to search for, e.g., xyz",
"type": "string"
}
},
"required": [
"ID",
"Query"
],
"type": "object"
}
},
"$ref": "#/definitions/SearchToolParams"
}
The funcschema
subpackage offers several options:
SchemaFromStruct[T]()
- Generate schema directly from a struct typeNewSchemaFromFuncV2()
- Type-safe schema generation with genericsNewSchemaFromFunc()
- Non-generic version for compatibilityGetPropertiesMap()
- Convert schema to a properties map for LLM tool definitions
While primarily focused on JSON Schema, jobj
provides limited XML Schema generation via the GetXMLSchemaString()
method:
schema := NewHeadlineResponse()
schema.UseXML = true
xmlSchema := schema.GetXMLSchemaString()
XML support is limited to basic type mapping and does not implement the full XML Schema specification.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License
Copyright (c) 2025, github.com/mhpenta
All rights reserved.