-
Notifications
You must be signed in to change notification settings - Fork 123
Open
Description
Somewhat similar to #429 but more flexible and with keeping type annotations within the Avro schema, it would be great to generate a Go struct with custom types using annotations.
Specifically: add the ability to support specific annotations (go-type, go-key-type) similar to Java's but for go. The Go types would be expected to implement encoding.TextMarshaler/encoding.TextUnmarshaler (taking advantage of #68 and #327).
Example
Schema
record MyRecord {
@go-type("math/big.Float") string value;
@go-key-type("go.custom.com/ident.ID4") map<@go-type("math/big.Float") string> balances;
array<@go-type("math/big.Float") string> values;
@go-type("github.com/google/btree.BTreeG[int]") array<string> totals;
}Which results in the following schema
{
"type" : "record",
"name" : "MyRecord",
"fields" : [ {
"name" : "value",
"type" : {
"type" : "string",
"go-type" : "math/big.Float"
}
}, {
"name" : "balances",
"type" : {
"type" : "map",
"values" : {
"type" : "string",
"go-type" : "math/big.Float"
},
"go-key-type" : "go.custom.com/ident.ID4"
}
}, {
"name" : "values",
"type" : {
"type" : "array",
"items" : {
"type" : "string",
"go-type" : "math/big.Float"
}
}
}, {
"name" : "totals",
"type" : {
"type" : "array",
"items" : "string",
"go-type" : "github.com/google/btree.BTreeG[int]"
}
} ]
}Gen cmd
avrogen -p main MyRecord.avscActual Output
package main
// Code generated by avro/gen. DO NOT EDIT.
// MyRecord is a generated struct.
type MyRecord struct {
Value string `avro:"value"`
Balances map[string]string `avro:"balances"`
Values []string `avro:"values"`
Totals []string `avro:"totals"`
}Desired Output
package main
import (
"math/big"
"github.com/google/btree"
"go.custom.com/ident"
)
// Code generated by avro/gen. DO NOT EDIT.
// MyRecord is a generated struct.
type MyRecord struct {
Value big.Float `avro:"value" json:"value"`
Balances map[ident.ID4]big.Float `avro:"balances" json:"balances"`
Values []big.Float `avro:"values" json:"values"`
Totals btree.BTreeG[int] `avro:"totals" json:"totals"`
}Notes
Potential pain points are:
- Extract the actual type and package to import from the fully qualified type in the
go-typeannotation.
For complex cases, extra annotations should be considered... SQLC which also allows go type override handles this decently. Taking inspiration from their doc, this would define:go-type-import: Import path of the package.go-type-pkg: Package name if it doesn't match the import path.go-type-name: The actual Go type namego-type-ptr: Whether to use a pointer or the type directly.This could also be done with a
["null", T]union. But there might be some cases where specifying a union in Avro is not desirable, yet a pointer might be useful in Go.)- Accordingly for map key type annotation, the corresponding
go-key-type-import,go-key-type-pkg,go-key-type-name,go-key-type-ptrannotations.
- Generating clean import statements (without duplicates, in order and formatted correctly). It could be alleviated using
goimports. - The last annotation in the example (
@go-type("github.com/google/btree.BTreeG[int]") array<string> totals;) is a bit more tricky as it is overwriting the array type. Marshaling to and from that type is not supported as it is not a string type supportingencoding.TextMarshaler/encoding.TextUnmarshaler. Overriding array (and map!) types be ignored (potentially with a warning/error) until marshaling can be handled for array, map or even arbitrary types.
Metadata
Metadata
Assignees
Labels
No labels