jettison icon indicating copy to clipboard operation
jettison copied to clipboard

Error when marshalling a structure with a field being an interface

Open ziemekobel-ef opened this issue 1 year ago • 2 comments

When trying to marshal a structure that has a field declared as an interface, an error gets returned. Tested using Go 1.21, MacOS 14.0, M1 Pro.

The following test demonstrates it:

package lib

import (
	"testing"

	"github.com/wI2L/jettison"
)

type Circle struct {
	Radius int `json:"radius"`
}

func (c Circle) Area() int {
	return c.Radius * c.Radius
}

type Shape interface {
	Area() int
}

type Foo struct {
	S Shape `json:"s"`
}

func TestJettisonMarshal(t *testing.T) {
	foo := Foo{S: Circle{Radius: 1}}

	_, err := jettison.Marshal(foo)
	if err != nil {
		t.Fatal(err)
	}
}

returns:

=== RUN   TestJettisonMarshal
runtime: nameOff 0x2af780 out of range 0x10029c000 - 0x1002d5a08
fatal error: runtime: name offset out of range

goroutine 6 [running]:
runtime.throw({0x1002704f4?, 0x14000003ba0?})
	/usr/local/go/src/runtime/panic.go:1077 +0x40 fp=0x14000125570 sp=0x14000125540 pc=0x1001994c0
runtime.resolveNameOff(0x14000125608?, 0x2af780)
	/usr/local/go/src/runtime/type.go:119 +0x214 fp=0x140001255d0 sp=0x14000125570 pc=0x1001c2f04
reflect.resolveNameOff(0x1400000e101?, 0x2d3f48?)
	/usr/local/go/src/runtime/runtime1.go:604 +0x1c fp=0x140001255f0 sp=0x140001255d0 pc=0x1001c8b1c
reflect.(*rtype).nameOff(...)
	/usr/local/go/src/reflect/type.go:526
reflect.(*rtype).String(0x1002d3f48)
	/usr/local/go/src/reflect/type.go:542 +0x24 fp=0x14000125610 sp=0x140001255f0 pc=0x1001fa964
fmt.(*pp).handleMethods(0x1400007ad00, 0x418108?)
	/usr/local/go/src/fmt/print.go:673 +0x21c fp=0x14000125870 sp=0x14000125610 pc=0x100206b9c
fmt.(*pp).printArg(0x1400007ad00, {0x1002ce3c0?, 0x1002d3f48}, 0x73)
	/usr/local/go/src/fmt/print.go:756 +0x5fc fp=0x14000125910 sp=0x14000125870 pc=0x1002075cc
fmt.(*pp).doPrintf(0x1400007ad00, {0x10026e5ea, 0x1a}, {0x14000125ab8?, 0x1, 0x1})
	/usr/local/go/src/fmt/print.go:1077 +0x2dc fp=0x14000125a20 sp=0x14000125910 pc=0x100209dcc
fmt.Sprintf({0x10026e5ea, 0x1a}, {0x14000125ab8, 0x1, 0x1})
	/usr/local/go/src/fmt/print.go:239 +0x4c fp=0x14000125a80 sp=0x14000125a20 pc=0x10020462c
github.com/wI2L/jettison.(*UnsupportedTypeError).Error(0x1002d5701?)
	/Users/ziemekobel/go/pkg/mod/github.com/w!i2!l/[email protected]/json.go:67 +0x50 fp=0x14000125ad0 sp=0x14000125a80 pc=0x100264060
fmt.(*pp).handleMethods(0x1400007a9c0, 0x0?)
	/usr/local/go/src/fmt/print.go:667 +0x158 fp=0x14000125d30 sp=0x14000125ad0 pc=0x100206ad8
fmt.(*pp).printArg(0x1400007a9c0, {0x1002b03e0?, 0x140000242b0}, 0x76)
	/usr/local/go/src/fmt/print.go:756 +0x5fc fp=0x14000125dd0 sp=0x14000125d30 pc=0x1002075cc
fmt.(*pp).doPrintln(0x1400007a9c0, {0x14000125f48?, 0x1, 0x14000024220?})
	/usr/local/go/src/fmt/print.go:1223 +0x3c fp=0x14000125e50 sp=0x14000125dd0 pc=0x10020acfc
fmt.Sprintln({0x14000125f48, 0x1, 0x1})
	/usr/local/go/src/fmt/print.go:321 +0x3c fp=0x14000125ea0 sp=0x14000125e50 pc=0x10020489c
testing.(*common).Fatal(0x14000003a00, {0x14000125f48?, 0x14000073f48?, 0x1001de19c?})
	/usr/local/go/src/testing/testing.go:1075 +0x3c fp=0x14000125f00 sp=0x14000125ea0 pc=0x10021f75c
ef-studio/catalyst/tests/lib.TestJettisonMarshal(0x14000003a00)
	/Users/ziemekobel/ws/ef-studio/backend/go/catalyst/tests/lib/jettison_test.go:30 +0x94 fp=0x14000125f60 sp=0x14000125f00 pc=0x100268bd4

ziemekobel-ef avatar Oct 05 '23 15:10 ziemekobel-ef

@ziemekobel-ef Can reproduce, but after a bit of digging, I'm still not sure how to fix this, so this might or might not be fixed in the future.

With the advent of encoding/json v2, and the fact that more performant custom JSON package exist, I'm not very keen to spend time working on this package.

wI2L avatar Oct 06 '23 14:10 wI2L

Yeah, I can totally understand it. TBH I would use goccy/go-json if they had FormatNilMapAsNull implemented. Encoding/json v2 does have it implemented, but for now for our payloads it is 30 % slower than standard encoding/json.

ziemekobel-ef avatar Oct 06 '23 16:10 ziemekobel-ef