大佬教程收集整理的这篇文章主要介绍了Golang中使用JSON的一些小技巧分享,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
前言
有的时候上游传过来的字段是String类型的,但是我们却想用变成数字来使用。 本来用一个json:",String" 就可以支持了,如果不知道golang的这些小技巧,就要大费周章了。
参考文章: JSON and struct composition in Go
临时忽略struct字段
type User struct { Email String `json:"email"` password String `json:"password"` // many more fields… }
临时忽略掉password字段
临时添加额外的字段
type User struct { Email String `json:"email"` password String `json:"password"` // many more fields… }
json.Marshal(struct { *User Token String `json:"token"` password bool `json:"password,Token: token,})
临时粘合两个struct
type BlogPost struct { URL String `json:"url"` title String `json:"title"` } type Analytics struct { Visitors int `json:"visitors"` PageViews int `json:"page_views"` } json.Marshal(struct{ *BlogPost *Analytics }{post,analytics})
一个json切分成两个struct
json.Unmarshal([]byte(`{ "url": "attila@attilaolah.eu","title": "Attila's Blog","visitors": 6,"page_views": 14 }`),&struct { *BlogPost *Analytics }{&post,&analytics})
临时改名struct的字段
type CacheItem struct { Key String `json:"key"` MaxAgE int `json:"cacheAge"` Value Value `json:"cacheValue"` } json.Marshal(struct{ *CacheItem // Omit bad keys OmitMaxAge omit `json:"cacheAge,omitempty"` OmitValue omit `json:"cacheValue,omitempty"` // Add nice keys MaxAgE int `json:"max_age"` Value *Value `json:"value"` }{ CacheItem: item,// Set thE int by value: MaxAge: item.MaxAge,// Set the nested struct by reference,avoid making a copy: Value: &item.Value,})
用字符串传递数字
这个对应的json是 {"Field1": "100"}
如果json是 {"Field1": 100} 则会报错
容忍字符串和数字互转
如果你使用的是jsoniter,可以启动模糊模式来支持 PHP 传递过来的 JSON。
import "github.com/json-iterator/go/extra" extra.RegisterFuzzyDecoders()
这样就可以处理字符串和数字类型不对的问题了。比如
又比如
var val float32 jsoniter.UnmarshalFromString(`"1.23"`,&val)
容忍空数组作为对象
PHP另外一个令人崩溃的地方是,如果 PHP array是空的时候,序列化出来是[]。但是不为空的时候,序列化出来的是{"key":"value"}
。 我们需要把 [] 当成 {} 处理。
如果你使用的是jsoniter,可以启动模糊模式来支持 PHP 传递过来的 JSON。
import "github.com/json-iterator/go/extra" extra.RegisterFuzzyDecoders()
这样就可以支持了
使用 MarshalJSON支持time.Time
golang 默认会把 time.Time
用字符串方式序列化。如果我们想用其他方式表示 time.Time
,需要自定义类型并定义 MarshalJSON。
type timeImplementedMarshaler time.Time func (obj timeImplementedMarshaler) MarshalJSON() ([]byte,error) { seconds := time.Time(obj).Unix() return []byte(strconv.FormaTint(seconds,10)),nil }
序列化的时候会调用 MarshalJSON
type TestObject struct { Field timeImplementedMarshaler } should := require.New(t) val := timeImplementedMarshaler(time.Unix(123,0)) obj := TestObject{val} bytes,err := jsoniter.Marshal(obj) should.Nil(err) should.Equal(`{"Field":123}`,String(bytes))
使用 RegisterTypeEncoder支持time.Time
jsoniter 能够对不是你定义的type自定义JSON编解码方式。比如对于 time.Time
可以用 epoch int64 来序列化
import "github.com/json-iterator/go/extra" extra.RegisterTimeAsInt64Codec(time.Microsecond) output,err := jsoniter.Marshal(time.Unix(1,1002)) should.Equal("1000001",String(output))
如果要自定义的话,参见 RegisterTimeAsInt64Codec 的实现代码
使用 MarshalText支持非字符串作为key的map
虽然 JSON 标准里只支持 String 作为 key 的 map。但是 golang 通过 @H_731_125@marshalText() 接口,使得其他类型也可以作为 map 的 key。例如
f,_,_ := big.ParseFloat("1",10,64,big.ToZero) val := map[*big.Float]String{f: "2"} str,err := MarshalToString(val) should.Equal(`{"1":"2"}`,str)
其中 big.Float 就实现了 MarshalText()
使用 json.Rawmessage
如果部分json文档没有标准格式,我们可以把原始的文本信息用String保存下来。
type TestObject struct { Field1 String Field2 json.Rawmessage } var data TestObject json.Unmarshal([]byte(`{"field1": "Hello","field2": [1,2,3]}`),&data) should.Equal(` [1,3]`,String(data.Field2))
使用 json.number
默认情况下,如果是 interface{}
对应数字的情况会是 float64 类型的。如果输入的数字比较大,这个表示会有损精度。所以可以 Usenumber()
启用 json.number
来用字符串表示数字。
decoder1 := json.NewDecoder(bytes.NewBufferString(`123`)) decoder1.Usenumber() var obj1 interface{} decoder1.Decode(&obj1) should.Equal(json.number("123"),obj1)
jsoniter 支持标准库的这个用法。同时,扩展了行为使得 Unmarshal 也可以支持 Usenumber 了。
json := Config{Usenumber:truE}.Froze() var obj interface{} json.UnmarshalFromString("123",&obj) should.Equal(json.number("123"),obj)
统一更改字段的命名风格
经常 JSON 里的字段名 Go 里的字段名是不一样的。我们可以用 field tag 来修改。
output,err := jsoniter.Marshal(struct { UserName String `json:"user_name"` FirstLanguage String `json:"first_language"` }{ UserName: "taowen",FirstLanguage: "Chinese",}) should.Equal(`{"user_name":"taowen","first_language":"Chinese"}`,String(output))
但是一个个字段来设置,太麻烦了。如果使用 jsoniter,我们可以统一设置命名风格。
import "github.com/json-iterator/go/extra" extra.SetNamingStrategy(LowerCaseWithUnderscores) output,err := jsoniter.Marshal(struct { UserName String FirstLanguage String }{ UserName: "taowen",}) should.Nil(err) should.Equal(`{"user_name":"taowen",String(output))
使用私有的字段
Go 的标准库只支持 public 的 field。jsoniter 额外支持了 private 的 field。需要使用 SupportPrivateFields()
来开启开关。
import "github.com/json-iterator/go/extra" extra.SupportPrivateFields() type TestObject struct { field1 String } obj := TestObject{} jsoniter.UnmarshalFromString(`{"field1":"Hello"}`,&obj) should.Equal("Hello",obj.field1)
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。
以上是大佬教程为你收集整理的Golang中使用JSON的一些小技巧分享全部内容,希望文章能够帮你解决Golang中使用JSON的一些小技巧分享所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。