a-h / generate

Generates Go (golang) Structs from JSON schema.
MIT License
444 stars 137 forks source link

AnyOf throws error when used with $refs #43

Open ocasta opened 6 years ago

ocasta commented 6 years ago

The attached Schema produces the error

Failure generating structs: missing types for Name with errors failed to get the type for Name with error failed to get a primitive type for schemaType and subtype , missing types for Name with errors failed to get the type for Name with error failed to get a primitive type for schemaType and subtype

mytest.txt

a-h commented 6 years ago

Thanks for the report, what do you think should happen here?

Since the Name field could be one of two types, then I guess the generator could be updated to return:

    return "interface{}", fmt.Errorf("failed to get a primitive type for schemaType '%s' and subtype '%s'",
        schemaType, subType)

Instead of undefined as the Go type, you'd get an output as below, so the Go code would compile and you could assign an Address or a Status to the Name field as appropriate. I think the error message should stay though, since it's not exactly what you'd expect. The error message could be nicer too.

// Code generated by schema-generate. DO NOT EDIT.

package main

// Address Address
type Address struct {
  County string `json:"county,omitempty"`
  District string `json:"district,omitempty"`
  FlatNumber string `json:"flatNumber,omitempty"`
  HouseName string `json:"houseName,omitempty"`
  HouseNumber string `json:"houseNumber,omitempty"`
  Postcode string `json:"postcode,omitempty"`
  Street string `json:"street,omitempty"`
  Town string `json:"town,omitempty"`
}

// Example example
type Example struct {
  Name interface{} `json:"name,omitempty"`
}

// Status
type Status struct {
  Favouritecat string `json:"favouritecat,omitempty"`
}
morangorin commented 6 years ago

Using interface{} would work. Another possible solution would be to declare a third structure such as, following the example above:

type StatusAddress struct {
  *Status
  *Address
}

and then

type Example struct {
  Name *StatusAddress `json:"name,omitempty"`
}

I am not sure which one is better. The simplicity of using interface{} is appealing.