[译]Golang中JSON和结构体的组合使用
2017-09-27 19:42
465 查看
原地址https://github.com/XanthusL/blog-gen
原文地址:http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/
假设你正在把一个JSON对象解码为Go的结构体。该JSON来自不受你控制的服务,因此你无法操作它的模式。但你想用不同的方式进行编码。
你可以随意使用
复杂度: 为了大型结构体添加大量额外代码
内存占用: 为了不分配不必要的内存需要尽量小心
其实,大多数情况下你可以在
下面是一些处理大结构体的一些小技巧。
现在你需要对
这里的技巧是我们不会设置
需要注意的是,没有必要声明
我们也可以只用匿名值:
去playground试试
另外需要注意的是,我们只包含了一个原始
去playground试试
去playground试试
去playground试试
下面是重命名两个结构体字段的例子,通过指针间接地使用嵌套的结构体,整型则直接复制:
去playground试试
需要注意的是,这只有在需要重命名一个大结构体中一两个字段的时候实用。当需要重命名所有字段时,通常建一个全新的对象(如 serialiser)更简单(代码也更干净),避免实用结构体组合的方式。
相关文章:
- JSON decoding in Go
原文地址:http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/
假设你正在把一个JSON对象解码为Go的结构体。该JSON来自不受你控制的服务,因此你无法操作它的模式。但你想用不同的方式进行编码。
你可以随意使用
json.Marshaler,但它有一些坑:
复杂度: 为了大型结构体添加大量额外代码
内存占用: 为了不分配不必要的内存需要尽量小心
其实,大多数情况下你可以在
MarshalJSON()中避免内存分配,但这会增加复杂度,因为这些处理在你的代码中(而不是
encoding/json),因此你得对它进行单元测试。这就需要撸更多枯燥的代码。
下面是一些处理大结构体的一些小技巧。
忽略字段
假设你有这么一个结构体:type User struct { Email string `json:"email"` Password string `json:"password"` // 大量字段。。。 }
现在你需要对
User进行转码,但不能包含
password字段。通过结构体组合处理这种情况的简单方法是用另一个结构体包裹它:
type omit *struct{} type PublicUser struct { *User Password omit `json:"password,omitempty"` } // 当你想对User进行编码时: json.Marshal(PublicUser{ User: user, })
这里的技巧是我们不会设置
PublishUser的
Password字段,由于是指针类型,它的默认值是
nil,并且会被忽略(因为设置了
omitempty)。
需要注意的是,没有必要声明
omit类型,我们可以用
*struct{}甚至
bool或
int。但是声明这个类型能够显示地表示我们要在输出中忽略该字段。使用哪个内建类型并不重要,只要它是能被
omitempty识别的零值。
我们也可以只用匿名值:
json.Marshal(struct { *User Password bool `json:"password,omitempty"` }{ User: user, })
去playground试试
另外需要注意的是,我们只包含了一个原始
User结构体的指针,这避免了复制一个新的
User。
增加额外字段
添加字段甚至比忽略字段更简单。继续我们之前的栗子,隐藏密码字段再暴露一个额外的token属性:
type omit *struct{} type PublicUser struct { *User Token string `json:"token"` Password omit `json:"password,omitempty"` } json.Marshal(PublicUser{ User: user, Token: token, })
去playground试试
组合结构体
这在组合来自不同服务的数据时很方便。举个例子,这是个含有统计数据的的BlogPost结构体:
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})
去playground试试
切分对象
这根组合结构体正好相反。就像我们对组合的结构体进行编码一样,我们也可以解码到分别使用JSON字段的结构体组合:json.Unmarshal([]byte(`{ "url": "attila@attilaolah.eu", "title": "Attila's Blog", "visitors": 6, "page_views": 14 }`), &struct { *BlogPost *Analytics }{&post, &analytics})
去playground试试
字段重命名
这个是移除字段和添加额外字段的组合使用:我们简单地移除一个字段再用一个不同的json:标记。这可以用指针的方式避免额外的内存分配。不过对于小的数据类型来说间接开销可能跟复制一份需要分配的内存相同,还要加上运行时开销。
下面是重命名两个结构体字段的例子,通过指针间接地使用嵌套的结构体,整型则直接复制:
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, })
去playground试试
需要注意的是,这只有在需要重命名一个大结构体中一两个字段的时候实用。当需要重命名所有字段时,通常建一个全新的对象(如 serialiser)更简单(代码也更干净),避免实用结构体组合的方式。
相关文章:
- JSON decoding in Go
相关文章推荐
- golang:json.Marshal转结构体,结构体属性为空
- Golang 中使用 JSON 的一些小技巧
- golang 使用json 包 实现序列化
- 在 golang 中使用 Json
- go、golang结构体对象转Json失败原因总结
- golang 结构体和 json 相互转换时的 key 匹配问题
- golang使用gin,gjson使现Http接口和Json解析
- golang结构体json的时间格式化解决方案
- golang--json使用笔记
- golang JSON的使用
- Golang 中使用 JSON 的一些小技巧 陶文 陶文 3 个月前 有的时候上游传过来的字段是string类型的,但是我们却想用变成数字来使用。 本来用一个json:",string" 就可以支持了
- Golang同步:条件变量和锁组合使用
- 『Golang』在Golang中使用json
- Go实战--golang中使用号称全世界最快的JSON解析器json-iterator(json-iterator/go)
- Golang web 开发实战之 session 缓存:如何使用 redigo 将一个结构体数据保存到 redis?
- Golang web 开发实战之 session 缓存:如何使用 redigo 将一个结构体数据保存到 redis?
- 使用for循环对 golang 中结构体数组取值进行修改时,需要注意的问题
- golang结构体json的时间格式化解决方案
- AndroidAsyncHttp与Gson或者Json组合使用,请求直接返回解析对象
- 在 golang 中使用 Json