【问题标题】:JSON key can either be a string or an objectJSON 键可以是字符串或对象
【发布时间】:2018-06-26 14:07:55
【问题描述】:

我想解析一些 JSON,但一个键是字符串或对象。

这是我当前的结构:https://github.com/PhillippOhlandt/pmtoapib/blob/master/CollectionItemRequest.go#L10

type CollectionItemRequest struct {
    Url         string          `json:"url"`
    Method      string          `json:"method"`
    Header      []RequestHeader `json:"header"`
    Body        RequestBody     `json:"body"`
    Description string          `json:"description"`
}

这里的“Url”属性不仅可以是字符串,还可以是对象。

我开始为它创建一个涵盖对象案例的自己的结构。

type CollectionItemRequestUrl struct {
    Raw string `json:"raw"`
}

type CollectionItemRequest struct {
    Url         CollectionItemRequestUrl `json:"url"`
    Method      string                   `json:"method"`
    Header      []RequestHeader          `json:"header"`
    Body        RequestBody              `json:"body"`
    Description string                   `json:"description"`
}

但是字符串版本将不再起作用。有没有办法让这两种情况都能正常工作并通过 getter 获取价值,比如request.Url.Get

编辑:

这是 JSON 的两个版本:

    "request": {
        "url": {
            "raw": "http://localhost:8081/users?per_page=5&page=2",
            "protocol": "http",
            "host": [
                "localhost"
            ],
            "port": "8081",
            "path": [
                "users"
            ],
            "query": [
                {
                    "key": "per_page",
                    "value": "5",
                    "equals": true,
                    "description": ""
                },
                {
                    "key": "page",
                    "value": "2",
                    "equals": true,
                    "description": ""
                }
            ],
            "variable": []
        },

"request": {
                "url": "http://localhost:8081/users/2",

注意:只有子集,整个 JSON 会太长。

【问题讨论】:

标签: json go decode


【解决方案1】:

拥有一个具有自定义解组方法的类型,该方法将首先解组到一个空接口,然后对它是否获得 stringmap[string]interface{} 进行类型切换,例如:

type example struct {
    URL myURL `json:"url"`
}

type myURL struct {
    url string
}

func (u *myURL) MarshalJSON() ([]byte, error) {
    return json.Marshal(u.url)
}

func (u *myURL) UnmarshalJSON(data []byte) error {
    var raw interface{}
    json.Unmarshal(data, &raw)
    switch raw := raw.(type) {
    case string:
        *u = myURL{raw}
    case map[string]interface{}:
        *u = myURL{raw["raw"].(string)}
    }
    return nil
}

const myStringURL string = `{"url": "http://www.example.com/as-string"}`
const myNestedURL string = `{"url": {"raw": "http://www.example.com/as-nested"}}`

func main() {
    var stringOutput example
    json.Unmarshal([]byte(myStringURL), &stringOutput)
    fmt.Println(stringOutput)

    var nestedOutput example
    json.Unmarshal([]byte(myNestedURL), &nestedOutput)
    fmt.Println(nestedOutput)
}

可在此处的 go playground 中运行:

https://play.golang.org/p/I6KC4aXHpxm

【讨论】:

  • 谢谢,这行得通!我已经在使用 UnmarshalJSON 方法的正确道路上,但在分配值时遇到了一些问题。
猜你喜欢
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多