diff --git a/jsonschema/LICENSE b/jsonschema/LICENSE new file mode 100644 index 00000000..508be926 --- /dev/null +++ b/jsonschema/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Go MCP SDK Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/jsonschema/README.md b/jsonschema/README.md new file mode 100644 index 00000000..f316bedd --- /dev/null +++ b/jsonschema/README.md @@ -0,0 +1,39 @@ +TODO: this file should live at the root of the jsonschema-go module, +above the jsonschema package. + +# JSON Schema for GO + +This module implements the [JSON Schema](https://json-schema.org/) specification. +The `jsonschema` package supports creating schemas, validating JSON values +against a schema, and inferring a schema from a Go struct. See the package +documentation for usage. + +## Contributing + +This module welcomes external contributions. +It has no dependencies outside of the standard library, and can be built with +the standard Go toolchain. Run `go test ./...` at the module root to run all +the tests. + +## Issues + +This project uses the [GitHub issue +tracker](https://github.com/TODO/jsonschema-go/issues) for bug reports, feature requests, and other issues. + +Please [report +bugs](https://github.com/TODO/jsonschema-go/issues/new). If the SDK is +not working as you expected, it is likely due to a bug or inadequate +documentation, and reporting an issue will help us address this shortcoming. + +When reporting a bug, make sure to answer these five questions: + +1. What did you do? +2. What did you see? +3. What did you expect to see? +4. What version of the Go MCP SDK are you using? +5. What version of Go are you using (`go version`)? + +## License + +This project is licensed under the MIT license. See the LICENSE file for details. + diff --git a/jsonschema/doc.go b/jsonschema/doc.go index f25b000a..135bdf50 100644 --- a/jsonschema/doc.go +++ b/jsonschema/doc.go @@ -5,22 +5,30 @@ /* Package jsonschema is an implementation of the [JSON Schema specification], a JSON-based format for describing the structure of JSON data. -The package can be used to read schemas for code generation, and to validate data using the -draft 2020-12 specification. Validation with other drafts or custom meta-schemas -is not supported. +The package can be used to read schemas for code generation, and to validate +data using the draft 2020-12 specification. Validation with other drafts +or custom meta-schemas is not supported. -Construct a [Schema] as you would any Go struct (for example, by writing a struct -literal), or unmarshal a JSON schema into a [Schema] in the usual way (with [encoding/json], -for instance). It can then be used for code generation or other purposes without -further processing. +Construct a [Schema] as you would any Go struct (for example, by writing +a struct literal), or unmarshal a JSON schema into a [Schema] in the usual +way (with [encoding/json], for instance). It can then be used for code +generation or other purposes without further processing. +You can also infer a schema from a Go struct. + +# Resolution + +A Schema can refer to other schemas, both inside and outside itself. These +references must be resolved before a schema can be used for validation. +Call [Schema.Resolve] to obtain a resolved schema (called a [Resolved]). +If the schema has external references, pass a [ResolveOptions] with a [Loader] +to load them. To validate default values in a schema, set +[ResolveOptions.ValidateDefaults] to true. # Validation -Before using a Schema to validate a JSON value, you must first resolve it by calling -[Schema.Resolve]. -The call [Resolved.Validate] on the result to validate a JSON value. -The value must be a Go value that looks like the result of unmarshaling a JSON -value into an [any] or a struct. For example, the JSON value +Call [Resolved.Validate] to validate a JSON value. The value must be a +Go value that looks like the result of unmarshaling a JSON value into an +[any] or a struct. For example, the JSON value {"name": "Al", "scores": [90, 80, 100]} @@ -41,8 +49,11 @@ or as a value of this type: # Inference The [For] function returns a [Schema] describing the given Go type. -The type cannot contain any function or channel types, and any map types must have a string key. -For example, calling For on the above Player type results in this schema: +Each field in the struct becomes a property of the schema. +The values of "json" tags are respected: the field's property name is taken +from the tag, and fields omitted from the JSON are omitted from the schema as +well. +For example, `jsonschema.For[Player]()` returns this schema: { "properties": { @@ -58,16 +69,32 @@ For example, calling For on the above Player type results in this schema: } } +Use the "jsonschema" struct tag to provide a description for the property: + + type Player struct { + Name string `json:"name" jsonschema:"player name"` + Scores []int `json:"scores" jsonschema:"scores of player's games"` + } + # Deviations from the specification -Regular expressions are processed with Go's regexp package, which differs from ECMA 262, -most significantly in not supporting back-references. +Regular expressions are processed with Go's regexp package, which differs +from ECMA 262, most significantly in not supporting back-references. See [this table of differences] for more. -The value of the "format" keyword is recorded in the Schema, but is ignored during validation. +The "format" keyword described in [section 7 of the validation spec] is recorded +in the Schema, but is ignored during validation. It does not even produce [annotations]. +Use the "pattern" keyword instead: it will work more reliably across JSON Schema +implementations. See [learnjsonschema.com] for more recommendations about "format". + +The content keywords described in [section 8 of the validation spec] +are recorded in the schema, but ignored during validation. [JSON Schema specification]: https://json-schema.org +[section 7 of the validation spec]: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7 +[section 8 of the validation spec]: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.8 +[learnjsonschema.org]: https://www.learnjsonschema.com/2020-12/format-annotation/format/ [this table of differences] https://github.com/dlclark/regexp2?tab=readme-ov-file#compare-regexp-and-regexp2 [annotations]: https://json-schema.org/draft/2020-12/json-schema-core#name-annotations */ diff --git a/jsonschema/infer.go b/jsonschema/infer.go index ae441291..654e6197 100644 --- a/jsonschema/infer.go +++ b/jsonschema/infer.go @@ -34,12 +34,13 @@ import ( // types, as they are incompatible with the JSON schema spec. // - maps with key other than 'string' // - function types +// - channel types // - complex numbers // - unsafe pointers // // It will return an error if there is a cycle in the types. // -// For recognizes struct field tags named "jsonschema". +// This function recognizes struct field tags named "jsonschema". // A jsonschema tag on a field is used as the description for the corresponding property. // For future compatibility, descriptions must not start with "WORD=", where WORD is a // sequence of non-whitespace characters.