在开发过程中 对 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"`
}
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))
}