最小代码结构
使用
自定义MarshalJSON只加在外层不会有这个问题,只要里面添加,目前发现不管外面的自定义MarshalJSON写不写,怎么写,都存在数据丢失的情况
问题原理
待进一步研究,简单看了下源码,跑了下,两个自定义MarshalJSON都会被执行,先内再外,目前没有深入研究
解决方法
线上发生情况是查询数据,最终返回树状结构数据,需要增加几个字段以及Children,为了便于理解和维护,没有改变原表结构体,直接用了,也就是上面最小代码结构的形式的复杂版,所以方向有几个:
- 不要使用组合,在原表上添加不映射列的字段,并写好备注,类似如下
缺点:直接拿这张表的数据的时候,会有很多默认的空值,容易造成歧义 - 把内部的MarshalJSON删掉
缺点:实际表使用的时候的需要自定义MarshalJSON的内容无法正常使用 - 不要用组合,而是给一个新字段,把两部分数据分开
缺点:用的时候稍微麻烦一点点,需要从里面取值 - 表和数据的返回结构完全分开,写两份
缺点:改表的字段后需要同步修改所有使用这个表的返回数据的字段 - 期待其他解决方法,目前暂时没发现,发现后更新
下面代码是用来断点调试看源码的测试代码
package main
import (
"encoding/json"
"log"
)
type Inter struct {
Title string `json:"title"`
}
func (r *Inter) MarshalJSON() ([]byte, error) {
type Alias Inter
return json.Marshal(&struct {
Title string `json:"title"`
Alias
}{
Title: r.Title,
Alias: (Alias)(*r),
})
}
type Test struct {
Inter
Name string `json:"name"`
Children *Test
}
type Test1 struct {
Inter Inter
Name string `json:"name"`
Children *Test
}
func (r *Test) MarshalJSON() ([]byte, error) {
type Alias Test
log.Println("----", r.Children)
return json.Marshal(&struct {
Children *Test
Name string
Alias
}{
Alias: (Alias)(*r),
Children: r.Children,
Name: r.Name,
})
}
func main() {
var tt []Test = make([]Test, 0)
tt = append(tt, Test{
Inter: Inter{Title: "title1"},
Name: "level1",
Children: nil,
})
tt = append(tt, Test{
Name: "level2",
Children: &Test{
Name: "2222",
},
})
ttStr, err := json.Marshal(tt)
if err != nil {
log.Println("--------err:---------")
log.Println(err)
return
}
log.Println(string(ttStr)) // [{"title":"title1"},{"title":""}]
log.Println("----------")
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。