Handle non-extensible nested objects

This commit is contained in:
Simon Ser 2022-10-06 16:13:46 +02:00
parent dde5b75d7a
commit 5e9f28cc05

View file

@ -19,16 +19,23 @@ func formatId(s string) string {
return s return s
} }
func refName(ref string) string {
prefix := "#/$defs/"
if !strings.HasPrefix(ref, prefix) {
return ""
}
return strings.TrimPrefix(ref, prefix)
}
func resolveRef(def *jsonschema.Schema, root *jsonschema.Schema) *jsonschema.Schema { func resolveRef(def *jsonschema.Schema, root *jsonschema.Schema) *jsonschema.Schema {
if def.Ref == "" { if def.Ref == "" {
return def return def
} }
prefix := "#/$defs/" name := refName(def.Ref)
if !strings.HasPrefix(def.Ref, prefix) { if name == "" {
log.Fatalf("unsupported $ref %q", def.Ref) log.Fatalf("unsupported $ref %q", def.Ref)
} }
name := strings.TrimPrefix(def.Ref, prefix)
result, ok := root.Defs[name] result, ok := root.Defs[name]
if !ok { if !ok {
@ -65,11 +72,23 @@ func schemaType(schema *jsonschema.Schema) jsonschema.Type {
} }
} }
func generateStruct(schema *jsonschema.Schema, root *jsonschema.Schema) jen.Code {
var fields []jen.Code
for name, prop := range schema.Properties {
id := formatId(name)
t := generateSchemaType(&prop, root)
tags := map[string]string{"json": name}
fields = append(fields, jen.Id(id).Add(t).Tag(tags))
}
return jen.Struct(fields...)
}
func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema) jen.Code { func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema) jen.Code {
if schema == nil { if schema == nil {
return jen.Interface() return jen.Interface()
} }
refName := refName(schema.Ref)
schema = resolveRef(schema, root) schema = resolveRef(schema, root)
switch schemaType(schema) { switch schemaType(schema) {
case jsonschema.TypeNull: case jsonschema.TypeNull:
@ -85,7 +104,15 @@ func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema) jen.
case jsonschema.TypeInteger: case jsonschema.TypeInteger:
return jen.Int64() return jen.Int64()
case jsonschema.TypeObject: case jsonschema.TypeObject:
if schema.AdditionalProperties != nil && schema.AdditionalProperties.IsFalse() && len(schema.PatternProperties) == 0 {
if refName != "" {
return jen.Id(formatId(refName))
} else {
return generateStruct(schema, root)
}
} else {
return jen.Map(jen.String()).Add(generateSchemaType(schema.AdditionalProperties, root)) return jen.Map(jen.String()).Add(generateSchemaType(schema.AdditionalProperties, root))
}
default: default:
return jen.Interface() return jen.Interface()
} }
@ -102,15 +129,7 @@ func generateDef(def *jsonschema.Schema, root *jsonschema.Schema, f *jen.File, n
return return
} }
var fields []jen.Code f.Type().Id(formatId(name)).Add(generateSchemaType(def, root)).Line()
for name, prop := range def.Properties {
id := formatId(name)
t := generateSchemaType(&prop, root)
tags := map[string]string{"json": name}
fields = append(fields, jen.Id(id).Add(t).Tag(tags))
}
f.Type().Id(formatId(name)).Struct(fields...).Line()
} }
func loadSchema(filename string) *jsonschema.Schema { func loadSchema(filename string) *jsonschema.Schema {