json解析库
json库
- JSON 编码: 将 Go 的数据结构转换为 JSON 格式的字符串。通过
json.Marshal函数实现。- JSON 解码: 将 JSON 格式的字符串转换为 Go 的数据结构。通过
json.Unmarshal函数实现。
相关的包:
1
2
3
import {
"encoding/json"
}
语法
1
2
json.Marshal(待解析map/struct数据)
json.Unmarshal(待解析json数据, &结果)
基础使用(推荐做法:始终使用标签)
一、序列化结构体(struct->json)
使用 json.Marshal 将数据序列化为字节数组。适用于结构体、Map。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Person struct {
Name string
Age int
Sex int
}
func main() {
person := Person{Name: "xiaoyu", Age: 18, Sex: 1}
b, err := json.Marshal(person) // 将结构体序列号为json字节数组
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(string(b)) // 将json字节数组转化为字符串
}
打印出:
1
{"Name":"xiaoyu","Age":18,"Sex":1}
注意:如果结构体中的字段为小写字母开头,将不能被序列化,因为这相当于是一个局部私有属性
如果想要输出的结果为小写字母开头的key,可以为结构体添加Tag:
1
2
3
4
5
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Sex int `json:"sex"`
}
这样的话,就可以输出:
1
{"name":"xiaoyu","age":18,"sex":1}
二、序列化Map(map->json)
1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
person := make(map[string]interface{}) // value为interface{}表示值可以是多种类型
person["name"] = "xiaoyu"
person["age"] = 18
person["sex"] = 1
b, err := json.Marshal(person) // 将Map序列号为json字节数组
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(string(b)) // 将json字节数组转化为字符串
}
打印出:
1
{"age":18,"name":"xiaoyu","sex":1}
三、反序列化为结构体(json->struct)
方式1
使用 json.Unmarshal 将字节数组反序列化。
使用条件: 确定你的 JSON 数据不包含大数字或你可以接受默认的 float64 处理方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func main() {
personStr := `{"name":"xiaoyu","age":18,"sex":1}`
person := new(Person)
err := json.Unmarshal([]byte(personStr), &person) // 将json字符串转化为byte数组,再填充到person
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(person)
fmt.Println(person.Name)
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Sex int `json:"sex"`
}
打印出:
1
2
&{xiaoyu 18 1}
xiaoyu
方式2
使用 json.Decoder 和 UseNumber
使用条件: 如果数据中包含大数字或需要更高精度的整数,建议使用 json.Decoder 和 UseNumber()
strings.NewReader更适合直接从字符串读取数据,使用更方便。bytes.NewReader适合处理字节切片,提供更大的灵活性。- 两者在功能上基本相同,主要区别在于输入数据的处理方式。
解决:
- 如果反序列化不指定结构体类型或者变量类型,则JSON中的数字类型,默认被反序列化成float64类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Person struct {
ID json.Number `json:"id"`
Name string `json:"name"`
}
func main() {
personStr := `{"id": 1234567890123456789, "name": "Alice"}`
var person Person
// 使用
decoder := json.NewDecoder(bytes.NewReader([]byte(personStr)))
decoder.UseNumber()
err := decoder.Decode(&person)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("ID: %v, Name: %s\n", person.ID, person.Name)
}
四、反序列化为Map(json->map)
1
2
3
4
5
6
7
8
9
10
11
func main() {
personStr := `{"name":"xiaoyu","age":18,"sex":1}`
person := make(map[string]interface{})
err := json.Unmarshal([]byte(personStr), &person) // 将json字符串转化为byte数组,再填充到person
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(person)
fmt.Println(person["name"])
}
打印出:
1
2
map[age:18 name:xiaoyu sex:1]
xiaoyu
Marshal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func TestJsonMarshalLength() {
tests := []interface{}{
nil,
struct{}{},
[]interface{}{},
map[string]interface{}{},
"",
0,
false,
}
for _, v := range tests {
data, _ := json.Marshal(v) // 100%完全不需要检查 len(data) == 0
fmt.Printf("%T: len=%d, data=%s\n", v, len(data), data)
}
}
1
2
3
4
5
6
7
<nil>: len=4, data=null
struct {}: len=2, data={}
[]interface {}: len=2, data=[]
map[string]interface {}: len=2, data={}
string: len=2, data=""
int: len=1, data=0
bool: len=5, data=false
Unmarshal 结构体字段赋予默认值 :crossed_swords:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
type Goods struct {
ShopID string `json:"shop_id"` // 零值 ""
OuterID int `json:"outer_id"` // 零值 0
UpdateTime time.Time `json:"update_time"`
// 数组
DescPics []string `json:"desc_pics"` // 零值 []
AllProps []Prop `json:"all_props"` // 零值 []
// 指针
CreateTime *time.Time `json:"create_time"` // 指针,零值=nil
GoodsHot *int `json:"goods_hot"` // 指针,零值=nil
PropsPtr *[]Prop `json:"props_ptr"` // 指针,零值=nil
// 嵌套, 也遵循零值规则
Props []Prop `json:"props"`
}
type Prop struct {
Source int `json:"source"`
PropName string `json:"prop_name"`
Value []string `json:"value"`
}
func main() {
fullJSON := `{
"update_time":"2025-11-10T17:05:28.919345+08:00",
"goods_hot":1,
"props": [
{
"source": 2,
"value": [
"IPad Pro(10.5寸)"
]
}
],
"presale_end_time":{"type":0,"value":"0001-01-01T00:00:00Z","description":""}
}`
var g Goods
_ = json.Unmarshal([]byte(fullJSON), &g)
fmt.Printf("\n完整输入后:%+v\n", g2)
}
结果
1
完整输入后:{ShopID: OuterID:0 UpdateTime:2025-11-10 17:05:28.919345 +0800 CST DescPics:[] AllProps:[] CreateTime:<nil> GoodsHot:0xc00009e038 PropsPtr:<nil> Props:[{Source:2 PropName: Value:[IPad Pro(10.5寸)]}]}
常用序列化/反序列化操作
指定字段名
1
2
3
4
5
6
7
8
9
10
11
12
13
// tag 是结构体的元信息,可以在运行的时候通过反射的机制读取出来
// 在 tag 中添加字段名,json 序列化/反序列化时会使用该字段名
type Person struct {
Name string `json:"name"` // 指定 json 序列化/反序列化时使用小写 name
Age int64 `json:"age"` // 指定 json 序列化/反序列化时使用小写 age
Height float64
}
p := Person{
Name: "Alice",
Age: 18,
Height: 160.7,
}
1
{"name":"Alice","age":18,"Height":160.7}
忽略某个字段
1
2
3
4
5
6
7
8
9
10
11
12
// 在 tag 中添加 "-",json 序列化/反序列化时会忽略该字段
type Person struct {
Name string `json:"name"` // 指定 json 序列化/反序列化时使用小写 name
Age int64 `json:"age"` // 指定 json 序列化/反序列化时使用小写 age
Height float64 `json:"-"` // 指定 json 序列化/反序列化时忽略此字段
}
p1 := Person{
Name: "Alice",
Age: 18,
Height: 160.7,
}
1
2
// Height 字段被忽略
{"name":"Alice","age":18}
忽略空值字段
omitempty 只管 Marshal(编码成 JSON),不管 Unmarshal(解码到 Go)。
- Marshal时: 字段如果是零值,且带了
omitempty,整条 key 都不会写出去,省空间。 - Unmarshal时:不会受
omitempty影响
⭐️ 未忽略空值字段
1
2
3
4
5
6
7
8
9
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Hobby []string `json:"hobby"`
}
u1 := User{
Name: "Alice",
}
1
2
// 空值字段不会被忽略
{"name":"Alice","email":"","hobby":null}
✏️ 忽略空值字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 在 tag 中添加 omitempty 会忽略空值
// 空值指的是 false、0、""、nil 指针、nil 接口、长度为 0 的数组、切片、映射
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"` // json 序列化时空值时忽略此字段, 反序列化不受影响
Hobby []string `json:"hobby,omitempty"`
}
u1 := User{
Name: "Alice",
}
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
}
func main() {
u1 := User{Name: "Alice"}
b, _ := json.Marshal(u1)
fmt.Println(string(b)) // 输出:{"name":"Alice"} // 添加 omitempty 后,空值字段会被忽略
}
指定匿名结构体字段
📚 嵌套结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile //不会有profile字段 // 默认忽略
}
type Profile struct {
Website string `json:"site"`
Slogan string `json:"slogan"`
}
u1 := User{
Name: "Alice",
Hobby: []string{"足球", "篮球"},
}
1
2
// 匿名嵌套 Profile 时,序列化后的 json 串为单层的
{"name":"Alice","hobby":["足球","篮球"],"site":"","slogan":""}
✌ 如果想要变成嵌套的json串,需要改为具名嵌套或定义字段tag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
Profile `json:"profile"` //会有profile字段
}
type Profile struct {
Website string `json:"site"`
Slogan string `json:"slogan"`
}
u1 := User{
Name: "Alice",
Hobby: []string{"足球", "篮球"},
}
1
2
// 定义字段 tag 后,序列化后的 json 串为双层的
{"name":"Alice","hobby":["足球","篮球"],"profile":{"site":"","slogan":""}}
✍ 如果想要忽略嵌套结构体空值字段,仅添加omitempty是不够的,需要使用嵌套的结构体指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Hobby []string `json:"hobby,omitempty"`
*Profile `json:"profile,omitempty"`
}
type Profile struct {
Website string `json:"site"`
Slogan string `json:"slogan"`
}
u1 := User{
Name: "七米",
Hobby: []string{"足球", "篮球"},
}
1
{"name":"七米","hobby":["足球","篮球"]}
不修改原结构体忽略空值字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 如果不需要将 User 结构体的 Password 字段序列化,但是又不想修改 User 结构体,
// 可以创建另外一个结构体匿名嵌套原 User,同时指定 Password 字段为匿名结构体指针类型,并添加 omitempty 标签
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
type NewUser struct {
*User // 匿名嵌套
Password *struct{} `json:"password,omitempty"` //json 序列化时空值时忽略此字段, 反序列化不受影响
}
func main() {
u := User{
Name: "Alice",
Password: "123456",
}
b, err := json.Marshal(NewUser{User: &u})
if err != nil {
fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
return
}
fmt.Printf("%s\n", b) // {"name":"Alice"}
}
使用匿名结构体添加字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 如果想扩展结构体字段,但有时候又没有必要单独定义新的结构体,可以使用匿名结构体简化操作
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
func main() {
u := User{
Name: "Alice",
Password: "123456",
}
// 使用匿名结构体内嵌 User 并添加额外字段Token
b, err := json.Marshal(struct {
*User
Token string `json:"token"`
}{
User: &u,
Token: "91je3a4s72d1da96h",
})
if err != nil {
fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
return
}
fmt.Printf("%s\n", b) // {"name":"Alice","password":"123456","token":"91je3a4s72d1da96h"}
}
使用匿名结构体组合多个结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 同理,可以使用匿名结构体来组合多个结构体来序列化与反序列化数据
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
type Post struct {
ID int `json:"id"`
Title string `json:"title"`
}
func main() {
u := User{
Name: "Alice",
Password: "123456",
}
p := Post{
ID: 123456,
Title: "hello world",
}
b, err := json.Marshal(struct {
*User
*Post
}{
User: &u,
Post: &p,
})
if err != nil {
fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
return
}
fmt.Printf("%s\n", b) // {"name":"Alice","password":"123456","id":123456,"title":"hello world"}
jsonStr := `{"name":"Alice","password":"123456","id":123456,"title":"Hello World"}`
var (
u2 User
p2 Post
)
if err := json.Unmarshal([]byte(jsonStr), &struct {
*User
*Post
}{&u2, &p2}); err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("%#v\n", u2) // main.User{Name:"Alice", Password:"123456"}
fmt.Printf("%#v\n", p2) // main.Post{ID:123456, Title:"Hello World"}
}
处理字符串格式数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 如果 json 串使用的是字符串格式的数字,可以在 tag 中添加 string 来告诉 json 包反序列化时从字符串解析相应字段
package main
import (
"encoding/json"
"fmt"
)
type Card struct {
ID int64 `json:"id,string"` // 添加 string tag
Score float64 `json:"score,string"` // 添加 string tag
}
func main() {
// json 串中使用的是字符串格式的数字,不添加 string tag 反序列会报错
jsonStr := `{"id": "1234567","score": "88.50"}`
var c1 Card
if err := json.Unmarshal([]byte(jsonStr), &c1); err != nil {
fmt.Printf("json.Unmarsha jsonStr1 failed, err:%v\n", err)
return
}
fmt.Printf("%#v\n", c1) // main.Card{ID:1234567, Score:88.5}
}
整数变为浮点数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// JSON 协议中没有整型和浮点型的区别,它们统称为 number
// 如果将 JSON 格式的数据反序列化为 map[string]interface{} 时,数字都变成科学计数法表示的浮点数
package main
import (
"encoding/json"
"fmt"
)
type student struct {
ID int64 `json:"id"`
Name string `json:"q1mi"`
}
func main() {
s := student{
ID: 123456789,
Name: "Alice",
}
b, _ := json.Marshal(s)
var m map[string]interface{}
_ = json.Unmarshal(b, &m)
fmt.Printf("%#v\n", m["id"]) // 1.23456789e+08
fmt.Printf("%T\n", m["id"]) // float64
}
如果想更合理的处理数字,需要使用decoder去反序列化,使用json.Number类型,示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type student struct {
ID int64 `json:"id"`
Name string `json:"q1mi"`
}
func main() {
s := student{
ID: 123456789,
Name: "Alice",
}
b, _ := json.Marshal(s)
// 使用功能 decoder 方式进行反序列,指定使用 number 类型
var m map[string]interface{}
decoder := json.NewDecoder(bytes.NewReader(b))
decoder.UseNumber()
_ = decoder.Decode(&m)
// 反序列后,类型为 json.Number 类型
fmt.Printf("%#v\n", m["id"]) // "123456789"
fmt.Printf("%T\n", m["id"]) // json.Number
// 根据字段的实际类型调用 Float64() 或 Int64() 函数获取对应类型
id, _ := m["id"].(json.Number).Int64()
fmt.Printf("%#v\n", id) // 123456789
fmt.Printf("%T\n", id) // int64
}
json.Number类型的源码定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// A Number represents a JSON number literal.
type Number string
// String returns the literal text of the number.
func (n Number) String() string { return string(n) }
// Float64 returns the number as a float64.
func (n Number) Float64() (float64, error) {
return strconv.ParseFloat(string(n), 64)
}
// Int64 returns the number as an int64.
func (n Number) Int64() (int64, error) {
return strconv.ParseInt(string(n), 10, 64)
}
处理不确定层级的 json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 如果 json 串没有固定格式导致不好定义与其相对应的结构体时,可以使用 json.RawMessage 将原始字节数据保存下来
package main
import (
"encoding/json"
"fmt"
)
type sendMsg struct {
User string `json:"user"`
Msg string `json:"msg"`
}
func main() {
jsonStr := `{"sendMsg":{"user":"Alice","msg":"永远不要高估自己"},"say":"Hello"}`
var data map[string]json.RawMessage
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
fmt.Printf("json.Unmarshal jsonStr failed, err:%v\n", err)
return
}
var msg sendMsg
if err := json.Unmarshal(data["sendMsg"], &msg); err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("%#v\n", msg) // main.sendMsg{User:"Alice", Msg:"永远不要高估自己"}
}
自定义序列化/反序列化
1
2
3
4
5
6
7
8
9
10
// 可以通过实现 json.Marshaler/json.Unmarshaler 接口来实现自定义的事件格式解析
// 解决方法: 实现Marshaler
type Marshaler interface {
MarshalJSON() ([]byte, error)
}
// 解决方法: 实现Unmarshaler
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
例子1
问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 内置的 json 包不识别常用的字符串时间格式,如 2022-05-24 14:50:00
package main
import (
"encoding/json"
"fmt"
"time"
)
type Post struct {
ID int `json:"id"`
Title string `json:"title"`
CreateTime time.Time `json:"create_time"` //
}
func main() {
// 序列化
p := Post{
ID: 123456,
Title: "hello world",
CreateTime: time.Now(),
}
b, err := json.Marshal(p)
if err != nil {
fmt.Printf("json.Marshal p1 failed, err:%v\n", err)
return
}
fmt.Printf("%s\n", b) // {"id":123456,"title":"hello world","create_time":"2022-05-24T14:58:45.3702937+08:00"}
// 反序列化
jsonStr := `{"id":123456,"title":"hello world","create_time":"2022-05-24 14:50:00"}`
var p2 Post
if err := json.Unmarshal([]byte(jsonStr), &p2); err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("%#v\n", p2) //报错: json.Unmarshal failed, err:parsing time "\"2022-05-24 14:50:00\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse " 14:50:00\"" as "T"
}
解决方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 通过实现 json.Marshaler/json.Unmarshaler 接口来自定义时间字段的事件格式解析
package main
import (
"encoding/json"
"fmt"
"time"
)
const layout = "2006-01-02 15:04:05"
type Post struct {
ID int `json:"id"`
Title string `json:"title"`
CreateTime time.Time `json:"create_time"`
}
// MarshalJSON 为 Post 类型自定义序列化方法
func (p Post) MarshalJSON() ([]byte, error) {
type TempPost Post // 定义与 Post 字段一致的新类型
return json.Marshal(struct {
*TempPost // 直接嵌套 Post 会进入死循环,需要使用新类型 TempPost
CreateTime string `json:"create_time"`
}{
TempPost: (*TempPost)(&p),
CreateTime: p.CreateTime.Format(layout),
})
}
// UnmarshalJSON 为 Post 类型自定义反序列化方法
func (p *Post) UnmarshalJSON(data []byte) error {
type TempPost Post // 定义与 Post 字段一致的新类型
tp := struct {
*TempPost // 直接嵌套 Post 会进入死循环,需要使用新类型 TempPost
CreateTime string `json:"create_time"`
}{
TempPost: (*TempPost)(p),
}
if err := json.Unmarshal(data, &tp); err != nil {
return err
}
var err error
p.CreateTime, err = time.Parse(layout, tp.CreateTime)
if err != nil {
return err
}
return nil
}
func main() {
// 序列化
p := Post{
ID: 123456,
Title: "hello world",
CreateTime: time.Now(),
}
b, err := json.Marshal(p)
if err != nil {
fmt.Printf("json.Marshal p1 failed, err:%v\n", err)
return
}
fmt.Printf("%s\n", b) // {"id":123456,"title":"hello world","create_time":"2022-05-24 18:30:03"}
// 反序列化
jsonStr := `{"id":123456,"title":"hello world","create_time":"2022-05-24 14:50:00"}`
var p2 Post
if err := json.Unmarshal([]byte(jsonStr), &p2); err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("%#v\n", p2) // main.Post{ID:123456, Title:"hello world", CreateTime:time.Date(2022, time.May, 24, 14, 50, 0, 0, time.UTC)}
}
例子2
问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
type DWEventReq struct {
DEvent []DEvent `json:"-"` // 不直接序列化
}
type DEvent struct {
MsgType string `json:"msgType"` // 消息类型
PlatShopId string `json:"platShopId"` // 商家店铺Id
Paypload string `json:"paypload"` // 消息内容
Ts int64 `json:"ts"` // 消息时间戳
}
// 自定义反序列化方法,支持直接数组或包装对象
func (d *DWEventReq) UnmarshalJSON(data []byte) error {
// 尝试作为数组直接反序列化
var events []DEvent
if err := json.Unmarshal(data, &events); err == nil {
d.DEvent = events
return nil
}
return nil
}
func DWEvent(ctx context.Context, req *proto.DWEventReq, rsp *proto.DWEventRsp) error {
if req == nil || len(req.DEvent) == 0 {
logger.Errorf(ctx, "DwEvent request is empty or has no events")
return nil
}
reqBytes, err := json.Marshal(req.DEvent)
if err != nil {
logger.WithError(err).Errorf(ctx, "failed to marshal DEvent array")
return err
}
if len(reqBytes) == 0 {
logger.Errorf(ctx, "DwEvent reqBytes is empty")
return nil
}
logger.Debugf(ctx, "DwEvent reqBytes=[%s]", reqBytes)
// input msg to channel, async to handle
worker.Input(ctx, reqBytes)
return nil
}
使用
1
2
3
4
5
6
7
8
9
curl --location 'http://localhost:8095/message/event' \
--header 'Content-Type: application/json' \
--data '[
{
"msgType": "PRODUCT_ON_SALE",
"platShopId": "MH2zDrm1b1f2Sena",
...
}
]'
原因:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type DWEventReq struct {
DEvent []DEvent // 不能填json 标签
}
// 填了就变成下面这样传参了
{
"DEvent": [
{
"msgType": "order",
"platShopId": "123",
"paypload": "data",
"ts": 123456
}
]
}