goccy / go-json

Fast JSON encoder/decoder compatible with encoding/json for Go
MIT License
3.12k stars 148 forks source link

Multi-level embedded self-references will cause panic #513

Open ystyle opened 5 months ago

ystyle commented 5 months ago

Minimal reproducible code

package main

import (
    stdjson "encoding/json"
    "fmt"
    "github.com/goccy/go-json"
)

type Customer struct {
    TKID string       `gorm:"primarykey;not null;type:varchar(255);"`
    IDs  []*IDMapping `gorm:"foreignKey:TKID;"`
}

type IDMapping struct {
    TKID     string `gorm:"comment:TKID;index:idx_tk_id;not null;type:varchar(255);"`
    Customer *Customer // when use MyCustomer will report an error when converted to json, Comment out this line and all serialization will not report errors
}

func main() {
    type MyCustomer struct {
        Customer
        MyField string
    }
    var list = []MyCustomer{
        {
            Customer: Customer{
                TKID: "1",
            },
            MyField: "111",
        },
    }
    bs, err := stdjson.Marshal(list) //1. std json no problem
    if err != nil {
        panic(err)
    }
    fmt.Println("std json:", string(bs)) 
    bs, err = json.Marshal(list[0].Customer) //2. goccy/go-json no problem
    if err != nil {
        panic(err)
    }
    fmt.Println("goccy/go-json(customer):", string(bs)) 
    bs, err = json.Marshal(list) //3. panic
    if err != nil {
        panic(err)
    }
    fmt.Println("goccy/go-json:", string(bs)) 
}

As shown in the sample code, MyCustomer will report an error when converted to json(Note 3), but it will not report an error when using the json of the standard library(Note 1). No error will occur when directly converting Customer without embedding(Note 2)