jtd-codegen should generate the following Go code:
type Thing struct {
Type string `json:"type"`
// Value can be the following types:
//
// - [A]
// - [B]
// - [C]
//
Value thingValue `json:"-"`
}
func (t *Thing) UnmarshalJSON(data []byte) error
func (t *Thing) MarshalJSON() ([]byte, error)
type thingValue interface {
isThing()
}
type ThingA struct{}
type ThingB struct{}
type ThingC struct{}
func (ThingA) isThing() {}
func (ThingB) isThing() {}
func (ThingC) isThing() {}
The user would consume the API like so:
var t Thing
switch v := t.Value.(type) {
case ThingA:
log.Println("thing contains type A")
case ThingB:
log.Println("thing contains type B")
case ThingC:
log.Println("thing contains type C")
default:
log.Println("thing contains unknown type")
}
If the user makes a mistake in the type-switch, the compiler will complain:
var t Thing
switch v := t.Value.(type) {
case ThingA:
log.Println("thing contains type A")
case string:
// does not even compile
}
This issue is an alternative to issue #49.
Rationale
Pros:
Using interfaces instead of flat structs can sometimes takes up less space in
memory if the mapping is large.
The user can use type-switches to determine the type of the value, which is
more idiomatic and safer in Go than using a string field.
Cons:
The magic field's name Value is not ideal. This is done because we can't
have custom marshalers and unmarshalers on an interface.
The magic field has an unexported type. Showing an unexported type in an
exported type is not ideal.
It's not explicit which types actually satisfy TValue outside a single
comment. This might be confusing to users.
Proposal
This issue proposes that for the following JSON type definition:
jtd-codegen
should generate the following Go code:The user would consume the API like so:
If the user makes a mistake in the type-switch, the compiler will complain:
This issue is an alternative to issue #49.
Rationale
Pros:
Cons:
Value
is not ideal. This is done because we can't have custom marshalers and unmarshalers on an interface.TValue
outside a single comment. This might be confusing to users.