Merge pull request #36 from goccy/feature/fix-string-pointer

Fix encoding of primitive pointer with string tag
This commit is contained in:
Masaaki Goshima 2020-08-20 22:02:57 +09:00 committed by GitHub
commit 51a1e71c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 2 deletions

View File

@ -542,8 +542,10 @@ func (e *Encoder) structHeader(fieldCode *structFieldCode, valueCode *opcode, ta
switch op {
case opStructFieldHead,
opStructFieldHeadOmitEmpty,
opStructFieldHeadStringTag,
opStructFieldHeadIndent,
opStructFieldHeadOmitEmptyIndent:
opStructFieldHeadOmitEmptyIndent,
opStructFieldHeadStringTagIndent:
return valueCode.beforeLastCode()
}
return (*opcode)(unsafe.Pointer(fieldCode))
@ -556,8 +558,10 @@ func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, tag
switch op {
case opStructField,
opStructFieldOmitEmpty,
opStructFieldStringTag,
opStructFieldIndent,
opStructFieldOmitEmptyIndent:
opStructFieldOmitEmptyIndent,
opStructFieldStringTagIndent:
return valueCode.beforeLastCode()
}
return code
@ -617,6 +621,16 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
f = f.nextField.toStructFieldCode()
}
}
if fieldNum == 1 && valueCode.op == opPtr {
// if field number is one and primitive pointer type,
// it should encode as **not** pointer .
switch valueCode.next.op {
case opInt, opInt8, opInt16, opInt32, opInt64,
opUint, opUint8, opUint16, opUint32, opUint64,
opFloat32, opFloat64, opBool, opString, opBytes:
valueCode = valueCode.next
}
}
key := fmt.Sprintf(`"%s":`, tag.key)
fieldCode := &structFieldCode{
opcodeHeader: &opcodeHeader{

View File

@ -1132,3 +1132,29 @@ func TestEncodeBytekind(t *testing.T) {
}
}
}
// golang.org/issue/8582
func TestEncodePointerString(t *testing.T) {
type stringPointer struct {
N *int64 `json:"n,string"`
}
var n int64 = 42
b, err := json.Marshal(stringPointer{N: &n})
if err != nil {
t.Fatalf("Marshal: %v", err)
}
if got, want := string(b), `{"n":"42"}`; got != want {
t.Errorf("Marshal = %s, want %s", got, want)
}
var back stringPointer
err = json.Unmarshal(b, &back)
if err != nil {
t.Fatalf("Unmarshal: %v", err)
}
if back.N == nil {
t.Fatalf("Unmarshaled nil N field")
}
if *back.N != 42 {
t.Fatalf("*N = %d; want 42", *back.N)
}
}