0

我正在向 Github 上名为jsonget的 Go 项目添加“数组通配符” 。这是我所说的数组通配符的一个例子:

 > echo "[{product:'coffee', price:2.10}, {product:'beer', price:3.80}]" | jsonget '*.price'

[2.10, 3.80]

我的分支的代码在这里

我遇到的问题是打字,当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"]

我想避免在这里使用反射,但我没有看到另一种方法来做到这一点。

4

1 回答 1

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()除了类型开关检测为整数的值之外的所有内容,这些值将按原样返回。

可能有一种更简洁的方法,但它几乎肯定会涉及大量代码重构。主要的缺点是现在您需要在使用之前检查一个值是否为 nil。

我不确定是否有办法使单个函数能够返回各种类型的值,因为我很确定它会对类型安全造成严重破坏。如果可能的话,我只能想象通过在函数定义中返回一个空接口来做到这一点。听起来很乱。

编辑:查看 Andrew Gerrand 的博客文章http://blog.golang.org/2011/01/json-and-go.html,尤其是关于解码通用数据的底部部分。它应该有帮助。

于 2013-05-15T12:25:44.853 回答