要用到的包
- gojsonq
- 获得方法:
go get github.com/thedevsaddam/gojsonq
用来解析的数据
//在 comment.json 文件里
{"CommentsCount1":
[
{
"SkuId":100003814753,
"ProductId":100003814753,
"CommentCountStr":"5万+",
"GoodRate":0.98,
"GeneralRate":0.015,
"PoorRate":0.005
}
],
"CommentsCount2":
[
{
"SkuId":100005671234,
"ProductId":100005671234,
"CommentCountStr":"3万+",
"GoodRate":0.97,
"GeneralRate":0.02,
"PoorRate":0.01
}
]
}
相关数据结构
- JSONQ 的结构。
type JSONQ struct {
option option // contains options for JSONQ
queryMap map[string]QueryFunc // contains query functions
node string // contains node name
raw json.RawMessage // raw message from source (reader, string or file)
rootJSONContent interface{} // original decoded json data
jsonContent interface{} // copy of original decoded json data for further processing
queryIndex int // contains number of orWhere query call
queries [][]query // nested queries
attributes []string // select attributes that will be available in final resuls
offsetRecords int // number of records that will be skipped in final result
limitRecords int // number of records that will be available in final result
distinctProperty string // contain the distinct attribute name
errors []error // contains all the errors when processing
}
- option 的结构。
// option describes type for providing configuration options to JSONQ
type option struct {
decoder Decoder
separator string
}
- RawMessage 实际上就是 []byte。
// RawMessage is a raw encoded JSON value.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage []byte
- query 的结构。
// query describes a query
type query struct {
key, operator string
value interface{}
}
一步一步来分析
读取文件加载数据
import (
"fmt"
"github.com/thedevsaddam/gojsonq"
)
- 加载文件
jsonq := gojsonq.New()
//返回 JSONQ 指针,jsonq --> *JSONQ
- New() 函数的代码如下所示:
// New returns a new instance of JSONQ,返回一个 JSONQ 实例
func New(options ...OptionFunc) *JSONQ {
jq := &JSONQ{
queryMap: defaultQueries(),
option: option{
decoder: &DefaultDecoder{},
separator: defaultSeparator,
},
}
for _, option := range options {
if err := option(jq); err != nil {
jq.addError(err)
}
}
return jq
}
- 定位到 json 文本的某个节点。
node := json.From("CommentsCount1")
- From(node string) 方法的代码如下所示:
// From seeks the json content to provided node. e.g: "users.[0]" or "users.[0].name"
func (j *JSONQ) From(node string) *JSONQ {
j.node = node
v, err := getNestedValue(j.jsonContent, node, j.option.separator)
if err != nil {
j.addError(err)
}
j.jsonContent = v
return j
}
- 从查询到的节点中选择属性。
attrVal := node.Select("CommentCountStr")
- Select(properties …string) 的代码如下所示:
// Select use for selection of the properties from query result
func (j *JSONQ) Select(properties ...string) *JSONQ {
j.attributes = append(j.attributes, properties...)
return j
}
//实际上,它就是把你要查找的属性添加到 attributes 属性切片里
- 上一步已经决定查找哪些属性的值了,那么现在就让我们来查看属性值是什么吧。
val := attrVal.Get()
- Get() 的代码有点复杂,但是我们只要搞清楚它返回的是个什么类型的值就好了,通过源码我们发现,它返回的是个 interface{},更进一步的,我们输出上面 val,查看它的值是什么。
[map[CommentCountStr:5万+]]
- 我们发现,首先它是一个切片,然后切片里存储的数据类型是 map,那么我们现在可以利用类型断言来处理我们获得最终结果。
//一步一步来,不着急
commentCountStrInterSlice := val.([]interface{})
commentCountStrMap := commentCountStrInterSlice[0].(map[string]interface{})
commentCountStr := commentCountStrMap["CommentCountStr"].(string)
- 我也可以一步整到位,套娃呗。
commentCountStr := (val.([]interface{}))[0].(map[string]interface{})["CommentCountStr"].(string)
读取字符串加载数据
- 其实这一节与上一节唯一不同的地方就是数据不是从文件里加载而来,而是从字符串加载,其他步骤都一样,但是额外还想说的就是,前面一节我们只介绍了如何查找一个属性的值是多少,我们其实还可以一次性查看多个属性的值分别是多少。
- 首先从字符串里加载数据。
jsonText := `
{"CommentsCount1":
[
{
"SkuId":100003814753,
"ProductId":100003814753,
"CommentCountStr":"5万+",
"GoodRate":0.98,
"GeneralRate":0.015,
"PoorRate":0.005
}
],
"CommentsCount2":
[
{
"SkuId":100005671234,
"ProductId":100005671234,
"CommentCountStr":"3万+",
"GoodRate":0.97,
"GeneralRate":0.02,
"PoorRate":0.01
}
]
}`
jsonq := gojsonq.New().FromString(jsonText)
- 定位到某个节点处。
node := jsonq.From("CommentsCount1")
- 选择属性。
//这次我们一次性多选几个属性
attrVal:= node.Select("CommentCountStr", "GoodRate", "GeneralRate", "PoorRate")
- 让我们看看此时 attrVal 是多少。
[map[CommentCountStr:5万+ GeneralRate:0.015 GoodRate:0.98 PoorRate:0.005]]
- 获得属性值。
vals := attrVal.Get()
- 类型断言。
valSlice := vals.([]interface{})
commentCountStr := valSlice[0].(map[string]interface{})["CommentCountStr"].(string)
goodRate := valSlice[0].(map[string]interface{})["GoodRate"].(float64)
generalRate := valSlice[0].(map[string]interface{})["GeneralRate"].(float64)
poorRate := valSlice[0].(map[string]interface{})["PoorRate"].(float64)
- 最后输出,查看一下。
fmt.Println(commentCountStr, goodRate, generalRate, poorRate)
输出结果如下:
5万+ 0.98 0.015 0.005