-
Notifications
You must be signed in to change notification settings - Fork 121
Description
I have a use-case where I dynamically want to build JSON schema's from Go based on information from the database. I thought I would be able to do this with this library, but when implementing it I found out that the JSONSchema() and JSONSchemaExtend() interfaces do not give you access to the actual data of the struct. Any chance support for this could be added?
The main reason is because of the following 2 locations:
https://github.com/invopop/jsonschema/blob/main/reflect.go#L164 (directly drops the actual value)
https://github.com/invopop/jsonschema/blob/main/reflect.go#L360 (makes a new instance of the struct)
I think it could be relatively simple to store the original value (perhaps make it optional on the reflector?) and make it available in JSONSchema()/JSONSchemaExtend().
Example code:
package main
import (
"encoding/json"
"log"
"github.com/invopop/jsonschema"
)
type PropertyMap struct {
PropertyNames []string
PropertyValues map[string]any
}
func (pm PropertyMap) MarshalJSON() ([]byte, error) {
return json.Marshal(pm.PropertyValues)
}
func (pm PropertyMap) JSONSchema() *jsonschema.Schema {
baseSchema := &jsonschema.Schema{
Type: "object",
}
for i := range pm.PropertyNames {
propertySchema := jsonschema.Reflect(pm.PropertyValues[pm.PropertyNames[i]])
baseSchema.Properties.Set(pm.PropertyNames[i], propertySchema)
}
return baseSchema
}
func main() {
newPropertyMap := &PropertyMap{
PropertyNames: []string{"field1", "field2"},
PropertyValues: map[string]any{
"field1": "yes",
"field2": "no",
},
}
jsonSchema := jsonschema.Reflect(newPropertyMap)
jsonSchemaData, err := jsonSchema.MarshalJSON()
log.Println(string(jsonSchemaData))
}Current output:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "#/$defs/PropertyMap",
"$defs": {
"PropertyMap": {
"type": "object"
}
}
}Expected output:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "#/$defs/PropertyMap",
"$defs": {
"PropertyMap": {
"type": "object"
"properties": {
"field1": {
"type": "string"
},
"field2": {
"type": "boolean"
}
}
}
}
}