diff --git a/go.mod b/go.mod index 48a823e..56769db 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/google/go-cmp v0.5.9 github.com/invopop/jsonschema v0.11.0 github.com/jpillora/longestcommon v0.0.0-20161227235612-adb9d91ee629 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 ) @@ -21,8 +22,10 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect golang.org/x/net v0.15.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/jsonschema/sanitize.go b/jsonschema/sanitize.go new file mode 100644 index 0000000..095074a --- /dev/null +++ b/jsonschema/sanitize.go @@ -0,0 +1,50 @@ +package jsonschema + +import ( + "net/url" + "strings" + + "github.com/invopop/jsonschema" + "golang.org/x/exp/maps" +) + +func Sanitize(sc *jsonschema.Schema) { + refs := collectRefs(sc) + + for key := range sc.Definitions { + if _, ok := refs[key]; !ok { + delete(sc.Definitions, key) + } + } + + for p := sc.Properties.Oldest(); p != nil; p = p.Next() { + Sanitize(p.Value) + } +} + +func collectRefs(sc *jsonschema.Schema) map[string]bool { + refs := make(map[string]bool) + if len(sc.Ref) > 0 { + refs[unescapeRef(sc.Ref)] = true + } + + for p := sc.Properties.Oldest(); p != nil; p = p.Next() { + maps.Copy(refs, collectRefs(p.Value)) + } + + return refs +} + +func unescapeRef(ref string) string { + ref = strings.TrimPrefix(ref, "#/$defs/") + + var err error + ref, err = url.PathUnescape(ref) + if err != nil { + panic(err) + } + + ref = strings.ReplaceAll(ref, "~1", "/") + ref = strings.ReplaceAll(ref, "~0", "~") + return ref +} diff --git a/jsonschema/sanitize_test.go b/jsonschema/sanitize_test.go new file mode 100644 index 0000000..87df8ae --- /dev/null +++ b/jsonschema/sanitize_test.go @@ -0,0 +1,21 @@ +package jsonschema + +import ( + "testing" + + "github.com/invopop/jsonschema" + "github.com/stretchr/testify/require" +) + +func TestSanitize(t *testing.T) { + sc := &jsonschema.Schema{ + Properties: jsonschema.NewProperties(), + } + + sc.Definitions = jsonschema.Definitions{ + "key": new(jsonschema.Schema), + } + + require.NotPanics(t, func() { Sanitize(sc) }) + require.Empty(t, sc.Definitions) +}