我正在努力将“数组通配符”添加到Github上名为jsonget的Go项目中。以下是数组通配符的含义示例:
> echo "[{product:'coffee', price:2.10}, {product:'beer', price:3.80}]" | jsonget '*.price'
[2.10, 3.80]
我的分支代码是here
我遇到的问题是键入,当GetValue
遇到*
字符时,它会递归,在子表达式上调用GetValue
,但类型总是以字符串形式返回
例如,在测试文件中,我给它一块json:
{
"inventory": [
{"name": "mountain bike", "price": 251.0},
{"name": "red wagon", "price": 90.10},
{"name": "kinesis advantage", "price": 300.0},
{"name": "a ticket to Mars", "price": 1200000000.0}
]
}
然后查询inventory[*].price
,期待[251,90.1,300,1.2e+09]
,而不是["251","90.1","300","1.2e+09"]
。
我想避免在这里使用反射,但我没有看到另一种方法来做到这一点。
答案 0 :(得分:1)
如果我误解了你的问题,我很抱歉,但希望这会有所帮助。
我认为您要么必须使用反射或类型切换(http://golang.org/doc/effective_go.html#type_switch,这可能会在幕后使用反射,而不是确定)。
修改现有的valueToString
函数以包含类型开关应该不会太难。可能将其重命名为convertValue
或更通用的东西,并在其中放置一个类型开关。如果值是int,则返回int,否则返回一个字符串。
例如:
func convertValue(value interface{}) (text string, i int, err error) { // Was valueToString
if value == nil && *printNulls == false {
return "", nil, nil
}
textBytes, err := json.Marshal(value)
if err != nil {
return "", nil, err
}
switch value := value.(type) {
default:
text = string(textBytes)
text = quotedString.ReplaceAllString(text, "$1")
return text, nil, nil
case int:
i = textBytes
return nil, i, nil
}
}
这将希望 string()
除了类型开关检测为int的值之外的所有内容,它们将按原样返回。
可能有一种更简洁的方法,但它几乎肯定会涉及大型代码重构。主要的缺点是现在你需要在使用它之前检查一个值是否为零。
我不确定是否有办法让一个函数能够返回各种类型的值,因为我很确定它会对类型安全造成严重破坏。如果有可能,我只能通过返回函数定义中的空接口来实现。听起来很乱。
编辑:查看Andrew Gerrand的博文http://blog.golang.org/2011/01/json-and-go.html,特别是关于解码通用数据的底线。它应该有所帮助。