Go Json 序列化笔记

在开发过程中 对 Json 的序列化 是经常要使用到的功能,而Golang 自带的 反序列化 在开发中经常 使用。

type Order struct {
		Id  uint32`json:"json"`
		Productname string `json:"productname"`
		Price float64 `json:"price"`
		Cratedate time.Time `json:"cratedate"`

	}

对于 实体数据 或数据库表 我们经常需要声明 结构体来实现建模。

Json序列化



	
	order := Order{
		Id:          1,
		Productname: "HuaWeiMate40",
		Price:       999,
		Cratedate:  time.Now(),
	}
	v,err := json.Marshal(&order)
	if err != nil{
		panic(err)
	}
	fmt.Println(string(v))

在这里插入图片描述

通过过声明 结构体 我们可以实现反序列化,其中要注意的一点 结构体 的变量首字母 必须要大写。

错误示范
type Order struct {
		id  uint32`json:"json"`
		productname string `json:"productname"`
		price float64 `json:"price"`
		cratedate time.Time `json:"cratedate"`

	}

我们 还可以通过 在结构体 变量名 后面通过 golang结构体的 Tag json:"xxx" 来 定义 反序列化后的名字。

对于 序列化,我们通常还需要捕捉下错误,来处理 处理失败的情况。

Json 反序列化

		jstr := `{"json":1,"productname":"HuaWeiMate40","price":999,"cratedate":"2020-10-01T10:05:22.890175+08:00"}`
	var order1 Order
	err = json.Unmarshal([]byte(jstr),&order1)
	if err != nil{
		panic(err)
	}
	fmt.Println(order1)

反序列化 将 json 字符串 转化成 Go的结构体。

复杂的Json 对象

在开发中 我们会常常遇到 复杂的Json 对象 ,多层嵌套 。

	var aax = `{
   "entity": "event",
   "account_id": "acc_FVIwUr1NaMxhtD",
   "event": "payout.processed",
   "contains": [
       "payout"
   ],
   "payload": {
       "payout": {
           "entity": {
               "id": "pout_FhyBjHSpDgzuhA",
               "entity": "payout",
               "fund_account_id": "fa_FhxMmjgd2qy0Nx",
               "amount": 200,
               "currency": "INR",
               "notes": [],
               "fees": 0,
               "tax": 0,
               "status": "processed",
               "purpose": "payout",
               "utr": "FhyBjHSpDgzuhA",
               "mode": "NEFT",
               "reference_id": null,
               "narration": "Gobull Technology Private Limi",
               "batch_id": null,
               "failure_reason": null,
               "created_at": 1601191285
           }
       }
   },
   "created_at": 1601261529
}`

对于 复杂的Json 对象 ,它的value 类型时不确定的 我们通常采用interface{}来表示任何类型。

var jsonobject map[string]interface{}
	err := json.Unmarshal([]byte(aax),&jsonobject)
	if err != nil{
		panic(err)
	}
	id := jsonobject["account_id"].(string)
	contains:= jsonobject["contains"].([]interface{})[0].(string)
	fund_account_id := jsonobject["payload"].(map[string]interface{})["payout"].(map[string]interface{})["entity"].(map[string]interface{})["id"].(string)
	fmt.Println(id,contains,fund_account_id)

在解析 复杂 json 时 对于 不确定的类型 通过[string]interface{} 来 存储,这使得我们 每解析一层就要 断言一层 。

另外 提一点 在 对 json字符串使用interface{}进行序列化后,默认是 float64 类型的

	var jsonobject map[string]interface{}
	var ax = `{"id": 12345}`
	err := json.Unmarshal([]byte(ax),&jsonobject)
	if err != nil{
		panic(err)
	}
	fmt.Println(jsonobject["id"].(float64))

封装解析Json字符串

对于 复杂的json 字符串 要写一大堆的map[string]interface{} 断言 那我们 可以简化下这个过程 把它封装下,让解析过程变得更加直观 看的懂。

var DefaultHandler ehandler
type ehandler func(*JsonParser)*JsonParser

type JsonParser struct {
	key string
	err error
	val map[string]interface{}
}

func NewJsonParser(err error,key string) *JsonParser {
	valx := make(map[string]interface{})
	return &JsonParser{val: valx,err: err,key: key}
}
func (self *JsonParser) Parse_Json(js []byte) *JsonParser{
	err := json.Unmarshal(js,&self.val)
	if err != nil{
		self.err = err
	}
	return self
}
func (self *JsonParser) Error() error{
	return self.err
}

func(self *JsonParser) Parse_Json_Next(key string) *JsonParser {
	if self.err != nil{
		return self
	}
	if _,ok := self.val[key];ok{
		aj := NewJsonParser(self.err,self.key)
		aj.val = self.val[key].(map[string]interface{})
		return aj
	}
	self.err = fmt.Errorf("Has no field %s error",key)
	return self
}

func(self *JsonParser) Unwarp_Or(f ehandler) *JsonParser {
	return f(self)
}
func(self *JsonParser) Unwarp() *JsonParser {
	return DefaultHandler(self)
}

func(self *JsonParser) Parse_Value(key string) interface{}{
	if self.err != nil{
		return nil
	}
	if val,ok := self.val[key];ok{
		return val
	}
	return nil
}

测试

	var aax = `{
   "entity": "event",
   "account_id": "acc_FVIwUr1NaMxhtD",
   "event": "payout.processed",
   "contains": [
       "payout"
   ],
   "payload": {
       "payout": {
           "entity": {
               "id": "pout_FhyBjHSpDgzuhA",
               "entity": "payout",
               "fund_account_id": "fa_FhxMmjgd2qy0Nx",
               "amount": 200,
               "currency": "INR",
               "notes": [],
               "fees": 0,
               "tax": 0,
               "status": "processed",
               "purpose": "payout",
               "utr": "FhyBjHSpDgzuhA",
               "mode": "NEFT",
               "reference_id": null,
               "narration": "Gobull Technology Private Limi",
               "batch_id": null,
               "failure_reason": null,
               "created_at": 1601191285
           }
       }
   },
   "created_at": 1601261529
}`
	a := NewJsonParser(nil,"")
	m := func(s *JsonParser)*JsonParser{
		fmt.Println("hahaha")
		return s
	}
	//自定义错误处理
	DefaultHandler = m
	//bb := a.Parse_Json_Next("payload").Unwarp().Parse_Json_Next("payout").Unwarp().Parse_Json_Next("entit").Unwarp().Pars_Value("id")
	jm := a.Parse_Json([]byte(aax))
	x := jm.Parse_Json_Next("payload").Parse_Json_Next("payout").Unwarp().Parse_Json_Next("entity")
	if x.Error() != nil{
		panic(x.Error())
	}
	x1 := x.Parse_Value("id")
	x2 := jm.Parse_Value("contains").([]interface{})
	fmt.Println(x1,x2)


对时间类型的序列化

在实际开发中,经常 会对时间 格式 有要求 而 默认的时间显示 可能不能满足要求,当反序列化时 我们要对特定的时间 序列化,那么我们可以通过自定义反序列化 方式

只要实现 UnmarshalJSON 和 MarshalJSON 这两个方法即可。

const (
	DateFormat = "01/02/2006"
	TimeFormat = "2006 01 02 15:04:05"
)

type Time time.Time

func Now() Time{
	return Time(time.Now())
}
func(t *Time) UnmarshalJSON(data []byte) (err error){
	now ,err := time.ParseInLocation(`"` + TimeFormat + `"`,string(data),time.Local)
	*t = Time(now)
	return
}
func (t Time) MarshalJSON() ([]byte,error){
	b := make([]byte,0,len(DateFormat) + 2)
	b = append(b,'"')
	b = time.Time(t).AppendFormat(b,DateFormat)
	b = append(b,'"')
	return b,nil
}
func(t Time) String() string{
	return time.Time(t).Format(TimeFormat)
}

type Mydate struct {
	a Time
}
func main(){
	var a Time
	a = Time(time.Now())
	b,err := json.Marshal(a)
	if err != nil{
		panic(err)
	}
	fmt.Println(string(b))
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值