Skip to content

Can't use information from struct in schema generation #138

@jerbob92

Description

@jerbob92

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"
                 }
            }
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions