天天看点

golang结构体嵌套json序列化丢失

package main

import (
	"encoding/json"
	"fmt"
)

type Tmsg struct {
	ID      int    `json:"id"`
	Message string `json:"message"`
}

func (me Tmsg) MarshalJSON() ([]byte, error) {
	type Alias Tmsg
	return json.Marshal(&struct {
		Message string `json:"message"`
		Alias
	}{
		Message: "1",
		Alias:   (Alias)(me),
	})
}

type tuser struct {
	Tid      int    `json:"id"`
	Realname string `json:"realname"`
}

type responseDataf struct {
	Tmsg
	Tuser *tuser `json:"user"`
}

func main() {

	user := tuser{
		Tid:      1,
		Realname: "aaaa",
	}

	msg := Tmsg{
		ID:      2,
		Message: "sssss",
	}
	data := responseDataf{
		msg,
		&user,
	}
	message, _ := json.Marshal(data)

	fmt.Println(string(message))
}

// output: {"message":"1","id":2}
           

上面代码输出不是预期的

{"id":2,"message":"sssss","user":{"id":1,"realname":"aaaa"}}

因为golang结构体组合的原因,在序列化时发现

Tmsg

有实现

MarshalJSON

,所以直接使用了我们自己实现的

MarshaJSON

。当然

Unmarshal

也存在这个问题

如果想要自定义json序列化,但是又想完整的输入内容,可以想下面这样更改,给

Tmsg

取个名字。不过输出和预期还是有点出入,但是影响不大。

package main

import (
	"encoding/json"
	"fmt"
)

type Tmsg struct {
	ID      int    `json:"id"`
	Message string `json:"message"`
}


type Tuser struct {
	ID      int    `json:"id"`
	Realname string `json:"realname"`
}

type responseDataf struct {
	Tg *Tmsg `json:"Tmsg"`
	Ter *Tuser `json:"Tuser"`
}

func (me Tmsg) MarshalJSON() ([]byte, error) {
	type Alias Tmsg
	return json.Marshal(&struct {
		Message string `json:"message"`
		Alias
	}{
		Message: "1",
		Alias:   (Alias)(me),
	})
}

func main() {

	user := Tuser{
		ID:1,
		Realname: "aaaa",
	}

	msg := Tmsg{
		ID:2,
		Message: "sssss",
	}
	data := responseDataf{
		Tg:&msg,
		Ter:&user,
	}
	message, _ := json.Marshal(data)
	fmt.Println(string(message))
}

// output: {"Tmsg":{"message":"1","id":2},"Tuser":{"id":1,"realname":"aaaa"}}
           

个人见解,如果有误还望斧正。

测试相关代码

https://github.com/whoisix/godemo/tree/master/json_struct

----更新----

发现github有一个issue https://github.com/golang/go/issues/39470