55package main
66
77import (
8- "encoding/json"
98 "fmt"
109 "maps"
1110 "os"
@@ -37,16 +36,17 @@ type TypeTemplate struct {
3736 // Fields holds the information for the field
3837 Fields []TypeFields
3938
40- // InterfaceType
41- InterfaceType string
42- // DiscriminatorKey
39+ // OneOfInterface is the name of the oneOf interface that this type should implement. By convention, all concrete types that implement a oneOf interface must define a single method, called "is${{.OneOfInterface}}", which accepts no arguments and has no return value.
40+ OneOfInterface string
41+
42+ // DiscriminatorKey is the name of the discriminator key used to determine the type of a complex oneOf field: commonly "type", "kind", etc.
4343 DiscriminatorKey string
44- // DiscriminatorType
44+ // DiscriminatorType is the generated type name of the discriminator field, and should be constructed as "{{.OneOfName}}Type": MetricType, ValueArrayType, etc.
4545 DiscriminatorType string
46- // DiscriminatorToType
47- DiscriminatorToType [][] string
48-
49- GenericFieldName string
46+ // DiscriminatorMappings maps oneOf enum constant (e.g. DatumTypeBool) to their concrete types (e.g. DatumBool).
47+ DiscriminatorMappings []DiscriminatorMapping
48+ // OneOfField is the name of the field that holds the oneOf variants (e.g., "Datum", "Values")
49+ OneOfField string
5050}
5151
5252// TypeFields holds the information for each type field
@@ -65,6 +65,12 @@ type EnumTemplate struct {
6565 Value string
6666}
6767
68+ // DiscriminatorMapping maps a discriminator enum value to its concrete type
69+ type DiscriminatorMapping struct {
70+ EnumConstant string // The enum constant to match in switch (e.g., "DatumTypeBool")
71+ ConcreteType string // The concrete type to unmarshal into (e.g., "DatumBool")
72+ }
73+
6874// ValidationTemplate holds information about the fields that
6975// need to be validated
7076type ValidationTemplate struct {
@@ -354,33 +360,35 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect
354360 }
355361 fmt .Fprint (f , "}\n " )
356362
357- if tt .DiscriminatorKey != "" && len (tt .DiscriminatorToType ) > 0 && tt .GenericFieldName != "" {
363+ if tt .DiscriminatorKey != "" && len (tt .DiscriminatorMappings ) > 0 && tt .OneOfField != "" {
358364 fmt .Fprintf (f , "func (v *%s) UnmarshalJSON(data []byte) error {\n " , tt .Name )
359365 fmt .Fprintf (f , "\t var peek struct {\n " )
360- fmt .Fprintf (f , "\t \t discriminator %s`json:\" %s\" `\n " , tt .DiscriminatorType , tt .DiscriminatorKey )
366+ fmt .Fprintf (f , "\t \t discriminator %s `json:\" %s\" `\n " , tt .DiscriminatorType , tt .DiscriminatorKey )
361367 fmt .Fprintf (f , "\t }\n " )
362368 fmt .Fprintf (f , "\t if err := json.Unmarshal(data, &peek); err != nil {\n " )
363369 fmt .Fprintf (f , "\t \t return err\n " )
364370 fmt .Fprintf (f , "\t }\n " )
365371 fmt .Fprintf (f , "\t switch peek.discriminator {\n " )
366372
367- for _ , dtt := range tt .DiscriminatorToType {
368- fmt .Fprintf (f , "\t case %s:\n " , dtt [ 0 ] )
369- fmt .Fprintf (f , "\t \t var val %s\n " , dtt [ 1 ] )
373+ for _ , mapping := range tt .DiscriminatorMappings {
374+ fmt .Fprintf (f , "\t case %s:\n " , mapping . EnumConstant )
375+ fmt .Fprintf (f , "\t \t var val %s\n " , mapping . ConcreteType )
370376 fmt .Fprintf (f , "\t \t if err := json.Unmarshal(data, &val); err != nil {\n " )
371377 fmt .Fprintf (f , "\t \t \t return err\n " )
372378 fmt .Fprintf (f , "\t \t }\n " )
373- fmt .Fprintf (f , "\t v.%s = val\n " , tt .GenericFieldName )
379+ fmt .Fprintf (f , "\t v.%s = val\n " , tt .OneOfField )
374380 }
375381
382+ fmt .Fprintf (f , "\t default:\n " )
383+ fmt .Fprintf (f , "\t \t return fmt.Errorf(\" unknown %s discriminator value: %%v\" , peek.discriminator)\n " , tt .DiscriminatorKey )
376384 fmt .Fprintf (f , "\t }\n " )
377385 fmt .Fprintf (f , "\t return nil\n " )
378386 fmt .Fprint (f , "}\n " )
379387 }
380388 }
381- if tt .InterfaceType != "" {
389+ if tt .OneOfInterface != "" {
382390 fmt .Fprintf (f , "\n " )
383- fmt .Fprintf (f , "func (%s) is%s() {}\n " , tt .Name , tt .InterfaceType )
391+ fmt .Fprintf (f , "func (%s) is%s() {}\n " , tt .Name , tt .OneOfInterface )
384392 }
385393 fmt .Fprint (f , "\n " )
386394 }
@@ -464,10 +472,8 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string
464472 typeTpl .Type = fmt .Sprintf ("[]%s" , s .Items .Value .Type )
465473 typeTpl .Name = typeName
466474 case "object" :
467- b , _ := json .Marshal (s )
468- fmt .Printf ("DEBUG IN OBJECT %s %+v %+v\n " , typeName , string (b ), enumFieldName )
469475 typeTpl = createTypeObject (s , name , typeName , formatTypeDescription (typeName , s ))
470- typeTpl .InterfaceType = interfaceName
476+ typeTpl .OneOfInterface = interfaceName
471477
472478 // Iterate over the properties and append the types, if we need to.
473479 properties := sortedKeys (s .Properties )
@@ -698,7 +704,6 @@ func createAllOf(s *openapi3.Schema, stringEnums map[string][]string, name, type
698704}
699705
700706func createOneOf (s * openapi3.Schema , name , typeName string ) ([]TypeTemplate , []EnumTemplate ) {
701- fmt .Printf ("DEBUG IN CREATEONEOF %v\n " , typeName )
702707 var parsedProperties []string
703708 var properties []string
704709 var genericTypes []string
@@ -748,10 +753,8 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E
748753 }
749754 }
750755
751- fmt .Printf ("DEBUG GENERIC TYPES %+v\n " , genericTypes )
752- typeInterfaces := map [string ]string {}
753756 maybeDiscriminators := map [string ]struct {}{}
754- discriminatorToType := [][] string {}
757+ discriminatorMappings := []DiscriminatorMapping {}
755758 discriminatorToDiscriminatorType := map [string ]string {}
756759 interfaceName := ""
757760
@@ -770,14 +773,12 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E
770773 propertyType := convertToValidGoType (prop , typeName , p )
771774
772775 if propertyType == "string" && len (p .Value .Enum ) == 1 {
773- fmt .Printf ("DEBUG PROP IS %s\n " , prop )
774776 maybeDiscriminators [prop ] = struct {}{}
775777 discriminatorToDiscriminatorType [prop ] = typeName + strcase .ToCamel (prop )
776- discriminatorToType = append (discriminatorToType , [] string {
777- fmt .Sprintf ("%s%s%s" , typeName , propertyName , strcase .ToCamel (p .Value .Enum [0 ].(string ))),
778- fmt .Sprintf ("%s%s" , typeName , strcase .ToCamel (p .Value .Enum [0 ].(string ))),
778+ discriminatorMappings = append (discriminatorMappings , DiscriminatorMapping {
779+ EnumConstant : fmt .Sprintf ("%s%s%s" , typeName , propertyName , strcase .ToCamel (p .Value .Enum [0 ].(string ))),
780+ ConcreteType : fmt .Sprintf ("%s%s" , typeName , strcase .ToCamel (p .Value .Enum [0 ].(string ))),
779781 })
780- // discriminatorToType[p.Value.Enum[0].(string)] = fmt.Sprintf("%s%s%s", typeName, propertyName, strcase.ToCamel(p.Value.Enum[0].(string)))
781782 }
782783 // Check if we have an enum in order to use the corresponding type instead of
783784 // "string"
@@ -796,11 +797,8 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E
796797
797798 // We set the type of a field as "any" if every element of the oneOf property isn't the same
798799 if slices .Contains (genericTypes , prop ) {
799- fmt .Printf ("DEBUG CONTAINS %+v %+v %s\n " , genericTypes , prop , typeName )
800800 interfaceName = fmt .Sprintf ("%s%s" , typeName , propertyName )
801801 field .Type = fmt .Sprintf ("%s%s" , typeName , propertyName )
802-
803- // typeInterfaces[field.Type] = fmt.Sprintf("%s%s", typeName, propertyName)
804802 }
805803
806804 // Check if the field is nullable and use omitzero instead of omitempty.
@@ -836,15 +834,7 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E
836834
837835 // TODO: This is the only place that has an "additional name" at the end
838836 // TODO: This is where the "allOf" is being detected
839- fmt .Printf ("DEBUG ABOUT TO POPULATE %s %+v %s\n " , name , enumFieldName , interfaceName )
840837 tt , et := populateTypeTemplates (name , v .Value , enumFieldName , interfaceName )
841-
842- fmt .Printf ("DEBUG TYPE INTERFACES %+v\n " , typeInterfaces )
843- // for idx := range tt {
844- // if interfaceType, ok := typeInterfaces[tt[idx].Name]; ok {
845- // tt[idx].InterfaceType = interfaceType
846- // }
847- // }
848838 typeTpls = append (typeTpls , tt ... )
849839 enumTpls = append (enumTpls , et ... )
850840 }
@@ -860,35 +850,31 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E
860850 discriminator := ""
861851 if len (maybeDiscriminators ) == 1 {
862852 discriminator = slices .Collect (maps .Keys (maybeDiscriminators ))[0 ]
863- fmt .Printf ("DEBUG DISCRIMINATOR %s\n " , discriminator )
864853 }
865854
866855 genericFieldName := ""
867856 if len (genericTypes ) == 1 {
868857 genericFieldName = strcase .ToCamel (genericTypes [0 ])
869858 }
870- fmt .Printf ("DEBUG GENERIC FIELD %+v %d %s\n " , genericTypes , len (genericTypes ), genericFieldName )
871859
872860 // Make sure to only create structs if the oneOf is not a replacement for enums on the API spec
873861 if len (fields ) > 0 {
874862 typeTpl := TypeTemplate {
875- Description : formatTypeDescription (typeName , s ),
876- Name : typeName ,
877- Type : "struct" ,
878- Fields : fields ,
879- DiscriminatorKey : discriminator ,
880- DiscriminatorType : discriminatorToDiscriminatorType [discriminator ],
881- DiscriminatorToType : discriminatorToType ,
882- GenericFieldName : genericFieldName ,
883- }
884- fmt .Printf ("DEBUG TT %+v\n " , typeTpl )
863+ Description : formatTypeDescription (typeName , s ),
864+ Name : typeName ,
865+ Type : "struct" ,
866+ Fields : fields ,
867+ DiscriminatorKey : discriminator ,
868+ DiscriminatorType : discriminatorToDiscriminatorType [discriminator ],
869+ DiscriminatorMappings : discriminatorMappings ,
870+ OneOfField : genericFieldName ,
871+ }
885872 typeTpls = append (typeTpls , typeTpl )
886873 }
887874
888875 if interfaceName != "" {
889876 typeTpls = append (typeTpls , TypeTemplate {
890877 Name : interfaceName ,
891- // Name: fmt.Sprintf("%s%s", typeName, interfaceName),
892878 Type : "interface" ,
893879 })
894880 }
0 commit comments