0

jsongetと呼ばれるGithubの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()、型スイッチが int として検出する値を除くすべての値がそのまま返されます。

おそらくもっとクリーンな方法がありますが、ほぼ確実に大規模なコード リファクタリングが必要になります。主な欠点は、値を使用する前に値が nil かどうかを確認する必要があることです。

単一の関数がさまざまな型の 1 つの値を返すことができるようにする方法があるかどうかはわかりません。型の安全性に問題があると確信しているためです。可能であれば、関数定義で空のインターフェイスを返すことでそれを行うことしか想像できません。乱雑に聞こえます。

編集: Andrew Gerrand のブログ投稿http://blog.golang.org/2011/01/json-and-go.html、特に一般的なデータのデコードに関する下部のビットを確認してください。それは役立つはずです。

于 2013-05-15T12:25:44.853 に答える