首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何向cobra提供JSON数组作为参数

如何向cobra提供JSON数组作为参数
EN

Stack Overflow用户
提问于 2021-12-09 06:03:48
回答 1查看 1.5K关注 0票数 2

我正在用Go和眼镜蛇库建造一个CLI。下面的JSON需要在相应的结构中反序列化。参数作为JSON数组:

代码语言:javascript
复制
"[
    (stringA, stringB), 
    stringC
 ]"

结构

代码语言:javascript
复制
type MyStruct struct {
    StringArray []string
}

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

代码语言:javascript
复制
cmd.PersistentFlags().StringSliceVarP(&opts.StringParam, "paramname", "", nil, `this is the description`)

但是眼镜蛇将传入的json读入为一个字符串[(stringA, stringB), stringC],而我希望数组的长度为2,例如StringArray:(stringA, stringB)和StringArray1stringC

我不能使用StringSliceVarP,因为它将根据我不想要的,进行拆分,因为我的数组字符串本身可能有一个,

我怎样才能做到这一点?

EN

回答 1

Stack Overflow用户

发布于 2021-12-31 12:14:00

我个人建议你不要这样做。提供格式化数据通常是通过读取STDIN或从文件完成的。这种解决方案通常更灵活,允许您添加标志来指定文件的格式(JSON、XML等)。

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

我个人的建议是:

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

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

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

代码语言:javascript
复制
type Value interface {
    String() string
    Set(string) error
    Type() string
}

要创建自定义JSON解析类型,可以编写以下代码来使用内置的encoding/json包:

代码语言:javascript
复制
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-compatible类型,可以编写如下内容:

代码语言:javascript
复制
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`)
}

示例用法:

代码语言:javascript
复制
$ 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
代码语言:javascript
复制
$ go run . mycmd --paramname '["(stringA, stringB)", "stringC"]'
myStruct.StringArray contains 2 elements:
idx=0: "(stringA, stringB)"
idx=1: "stringC"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70285369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档