actgardner / gogen-avro

Generate Go code to serialize and deserialize Avro schemas
MIT License
366 stars 87 forks source link

json.Marshal add M value for Maps #163

Closed a-watters closed 3 years ago

a-watters commented 3 years ago

Having defined a struct foo which contains a map fooMap the resulting json.Marshal adds an additional 'M' level to the json.

avsc file: { "namespace": "example.foo", "type": "record", "name": "foo", "fields": [ { "name": "fooMap", "type": { "type": "map", "values": "string" }, "golang.tags": "json:\"fooMap\"" } ] }

output json:

{"fooMap":{"M":{"key":"value"}}}

actgardner commented 3 years ago

This is a known issue with how the 6.x version of gogen-avro generates structs to store maps. The 7.x releases fixed this issue and should encode a map to JSON as expected. JSON encoding support is an ongoing effort, and my goal is to have 8.x be fully compliant with the Avro spec. Let me know if you have any issues with the 7.x or 8.x beta release!

a-watters commented 3 years ago

I'm seeing this issue using v7.3.0

someFooMap := avro.NewMapString() someFoo := avro.Foo{FooMap: someFooMap} jsonFoo, _ := json.Marshal(someFoo)

actgardner commented 3 years ago

Can you post the generated code for the map type?

a-watters commented 3 years ago

`// Code generated by github.com/actgardner/gogen-avro. DO NOT EDIT. /*

package foo

import ( "github.com/actgardner/gogen-avro/vm" "github.com/actgardner/gogen-avro/vm/types" "io" )

func writeMapString(r *MapString, w io.Writer) error { err := vm.WriteLong(int64(len(r.M)), w) if err != nil || len(r.M) == 0 { return err } for k, e := range r.M { err = vm.WriteString(k, w) if err != nil { return err } err = vm.WriteString(e, w) if err != nil { return err } } return vm.WriteLong(0, w) }

type MapString struct { keys []string values []string M map[string]string }

func NewMapString() *MapString { return &MapString{ keys: make([]string, 0), values: make([]string, 0), M: make(map[string]string), } }

func ( *MapString) SetBoolean(v bool) { panic("Unsupported operation") } func ( MapString) SetInt(v int32) { panic("Unsupported operation") } func (_ MapString) SetLong(v int64) { panic("Unsupported operation") } func ( *MapString) SetFloat(v float32) { panic("Unsupported operation") } func ( MapString) SetDouble(v float64) { panic("Unsupported operation") } func (_ MapString) SetBytes(v []byte) { panic("Unsupported operation") } func ( *MapString) SetString(v string) { panic("Unsupported operation") } func ( MapString) SetUnionElem(v int64) { panic("Unsupported operation") } func (_ MapString) Get(i int) types.Field { panic("Unsupported operation") } func (_ MapString) SetDefault(i int) { panic("Unsupported operation") } func (r MapString) Finalize() { for i := range r.keys { r.M[r.keys[i]] = r.values[i] } r.keys = nil r.values = nil }

func (r *MapString) AppendMap(key string) types.Field { r.keys = append(r.keys, key) var v string

r.values = append(r.values, v)

return (*types.String)(&r.values[len(r.values)-1])

}

func (_ *MapString) AppendArray() types.Field { panic("Unsupported operation") } `

actgardner commented 3 years ago

That doesn't look like code generated with v7, the imports and comment should be github.com/actgardner/gogen-avro/v7. Can you remove and reinstall the gogen-avro binary and regenerate the code?