猿问

如何在 Go 中解组可以是数组或字符串的字段?

我正在尝试解组此文件:


{

  "@babel/code-frame@7.0.0": {

    "licenses": "MIT",

    "repository": "https://github.com/babel/babel/tree/master/packages/babel-code-frame",

    "publisher": "Sebastian McKenzie",

    "email": "sebmck@gmail.com",

    "path": "/Users/lislab/workspace/falcon-enrolment/frontend-customer/node_modules/@babel/code-frame",

    "licenseFile": "/Users/lislab/workspace/falcon-enrolment/frontend-customer/node_modules/@babel/code-frame/LICENSE"

  },

  "json-schema@0.2.3": {

    "licenses": [

      "AFLv2.1",

      "BSD"

    ],

    "repository": "https://github.com/kriszyp/json-schema",

    "publisher": "Kris Zyp",

    "path": "/Users/lislab/workspace/falcon-enrolment/frontend-customer/node_modules/json-schema",

    "licenseFile": "/Users/lislab/workspace/falcon-enrolment/frontend-customer/node_modules/json-schema/README.md"

  }

}

进入这个结构:


type Dependency struct {

    Name    string

    URL     string

    Version string

    License string

}

使用这些说明:


dependencies := map[string]*json.RawMessage{}

err = json.Unmarshal(file, &dependencies)

// boilerplate


for key, value := range dependencies {

    depVal := map[string]string{}

    err = json.Unmarshal(*value, &depVal)

    // boilerplate

    result = append(result, depVal)

}

这个问题是在“json-schema@0.2.3”中我们有一组许可证而不是一个字符串,因此我显然得到了


json: cannot unmarshal array into Go value of type string 

有没有办法自动处理license可以是数组或字符串的字段?


慕运维8079593
浏览 102回答 1
1回答

慕田峪7331174

不幸的是,该软件包没有为此提供真正的自动解决方案json。但是您可以将依赖项解组为 amap[string]*json.RawMessage而不是map[string]string. json.RawMessage只是一个[]byte,因此您可以根据第一个字节来决定消息的类型。例子:for _, value := range dependencies {    depVal := map[string]*json.RawMessage{}    _ = json.Unmarshal(*value, &depVal)    // check if the first character of the RawMessage is a bracket    if rune([]byte(*depVal["licenses"])[0]) == '[' {        var licenses []string        json.Unmarshal(*depVal["licenses"], &licenses)        fmt.Println(licenses)        // do something with the array    }    result = append(result, Dependency{        URL:     string(*depVal["repository"]),        License: string(*depVal["licenses"]),    })}另一种解决方案是使用 2 个结构。一个包含字符串形式的依赖项,另一个包含数组形式的依赖项。然后您可以尝试json.Unmarshal同时调用它们。例子:type Dependency struct {    Licenses string    // other fields}type DependencyWithArr struct {    Licenses []string    // other fields}// in your functionfor _, value := range dependencies {    type1 := Dependency{}    type2 := DependencyWithArr{}    err = json.Unmarshal(*value, &type1)    if err != nil {        err = json.Unmarshal(*value, &type2)        // use the array type    } else {        // use the single string type    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答