我正致力于将“数组通配符”添加到 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"]
。
我想避免在这里使用反射,但我看不到另一种方法可以做到这一点。
最佳答案
如果我误解了您的问题,我深表歉意,但希望这对您有所帮助。
我认为您要么必须使用反射,要么必须使用类型开关( http://golang.org/doc/effective_go.html#type_switch ,它可能在幕后使用反射,对此我不确定)。
修改现有的 valueToString
函数以包含类型切换应该不会太难。可能将其重命名为 convertValue
或更通用的名称,并在其中放置一个类型开关。如果值为 int,则返回 int,否则返回 string。
例如:
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 的值之外的所有内容,这些值将按原样返回。
可能有更简洁的方法,但几乎肯定会涉及大量代码重构。主要缺点是现在您需要在使用前检查值是否为 nil。
我不确定是否有办法让单个函数能够返回各种类型的一个值,因为我很确定它会严重破坏类型安全。如果可能的话,我只能想象通过在函数定义中返回一个空接口(interface)来实现。听起来很乱。
编辑:查看 Andrew Gerrand 的博客文章 http://blog.golang.org/2011/01/json-and-go.html ,尤其是底部附近关于解码通用数据的位。它应该有所帮助。
关于json - 输入递归 golang 函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16556112/