如何将JSON数组作为参数提供给cobra-cli



我正在使用Go和Cobra库构建CLI。我有以下JSON,需要在相应的结构中进行反序列化。参数为JSON数组:

"[
(stringA, stringB), 
stringC
]"

结构

type MyStruct struct {
StringArray []string
}

我正在使用眼镜蛇的StringSicceVarP,如下所示

cmd.PersistentFlags().StringSliceVarP(&opts.StringParam, "paramname", "", nil, `this is the description`)

但是cobra将传入的json作为一个单独的字符串[(stringA, stringB), stringC]读取,而我希望数组的长度为2,这样StringArray[0]:(stringA, stringB)和StringArray[1]:stringC

我不能使用StringSliceVarP,因为它将基于,进行拆分,这是我不想要的,因为我的数组字符串本身可能有,

我怎样才能做到这一点?

我个人建议您不要使用此选项。提供格式化数据通常是通过读取STDIN或从文件中进行的。这种解决方案通常更灵活,允许您添加标志来指定文件的格式(JSON、XML等(

在自变量中提供文件名而不是原始JSON字符串可以增加与其他软件的更好的互操作性,以及其他好处,例如使用计算机的磁盘而不是计算机的内存/RAM来缓冲数据。

我个人的建议是:

  • 使用选项和配置的标志,类似于HTTP的查询参数
  • 对数据使用stdin/file句柄,类似于HTTP的请求体

但是,如果您坚持使用标志:

Cobra没有对JSON结构的内置支持。但是,pflag包(Cobra使用的标志库(允许您通过pflag.(*FlagSet).Var()方法定义要用作标志的自定义值类型。您必须制作一种实现pflag.Value接口的新类型:

type Value interface {
String() string
Set(string) error
Type() string
}

要制作自定义的JSON解析类型,可以编写以下内容来使用内置的encoding/json包:

import (
"encoding/json"
)
type JSONFlag struct {
Target interface{}
}
// String is used both by fmt.Print and by Cobra in help text
func (f *JSONFlag) String() string {
b, err := json.Marshal(f.Target)
if err != nil {
return "failed to marshal object"
}
return string(b)
}
// Set must have pointer receiver so it doesn't change the value of a copy
func (f *JSONFlag) Set(v string) error {
return json.Unmarshal([]byte(v), f.Target)
}
// Type is only used in help text
func (f *JSONFlag) Type() string {
return "json"
}

然后,要使用这种新的pflag.Value兼容类型,您可以编写如下内容:

import (
"fmt"
"github.com/spf13/cobra"
)
type MyStruct struct {
StringArray []string
}
func init() {
var flagMyStringArray []string
var myCmd = &cobra.Command{
Use:   "mycmd",
Short: "A brief description of your command",
Run: func(cmd *cobra.Command, args []string) {
myStruct := MyStruct{StringArray: flagMyStringArray}
fmt.Printf("myStruct.StringArray contains %d elements:n", len(myStruct.StringArray))
for i, s := range myStruct.StringArray {
fmt.Printf("idx=%d: %q", i, s)
}
},
}
rootCmd.AddCommand(myCmd)
myCmd.Flags().Var(&JSONFlag{&flagMyStringArray}, "paramname", `this is the description`)
}

示例用法:

$ go run . mycmd --paramname 'hello'
Error: invalid argument "hello" for "--paramname" flag: invalid character 'h' looking for beginning of value
Usage:
test mycmd [flags]
Flags:
-h, --help             help for mycmd
--paramname json   this is the description
exit status 1
$ go run . mycmd --paramname '["(stringA, stringB)", "stringC"]'
myStruct.StringArray contains 2 elements:
idx=0: "(stringA, stringB)"
idx=1: "stringC"

相关内容

  • 没有找到相关文章

最新更新