json - Go:解码具有多种类型的 JSON

标签 json go struct types unmarshalling

我在将 JSON 响应解码为结构时遇到问题。我遇到的问题是邮政编码可以作为字符串或整数返回。如何编写解码方法来检查 zip 是否为 int 并强制将其存储为字符串?

结构:

type CustomerAddress struct {
    Line1            string `json:"line1"`
    City             string `json:"city"`
    State            string `json:"state"`
    Zip              string `json:"zip"`
    IsPrimaryAddress string `json:"isPrimaryAddress"`
}

示例 Json:

address": [
  {
    "line1": "555 ADDRESS PLACE",
    "city": "DALLAS",
    "state": "TX",
    "isPrimaryAddress": "Y",
    "zip": 55555
  }
]

解码后,结果应成功将 zip 转换为字符串:

address": [
  {
    "line1": "555 ADDRESS PLACE",
    "city": "DALLAS",
    "state": "TX",
    "isPrimaryAddress": "Y",
    "zip": "55555"
  }
]

作为尝试,我尝试使用 ZipWrapper。

type CustomerAddress struct {
    Line1            string        `json:"line1"`
    City             string        `json:"city"`
    State            string        `json:"state"`
    Zip              ZipWrapper    `json:"zip"`
    IsPrimaryAddress string        `json:"isPrimaryAddress"`
}

type ZipWrapper struct {
   Zip string
}

func (w *ZipWrapper ) UnmarshalJSON(data []byte) (err error) {

    if zip, err := strconv.Atoi(string(data)); err == nil {
        w.Zip = strconv.Itoa(zip)
        return nil
    }
    return json.Unmarshal(data, &w.Zip)
}

除了 zip 现在是 CustomerAddress 中的嵌套结构外,这几乎可以正常工作,这不是我想要的:

  address": [
  {
    "line1": "555 ADDRESS PLACE",
    "city": "DALLAS",
    "state": "TX",
    "isPrimaryAddress": "Y",
    "zip": {
      "Zip": "55555"
    }
  }
]

有什么想法吗?我觉得这是一项相对容易的任务,但我是一个完全的 Go 菜鸟,还没有完全理解 Unmarshalling 的工作原理。

最佳答案

json 包提供了 json.Number键入以执行此操作:

type CustomerAddress struct {
    Line1            string      `json:"line1"`
    City             string      `json:"city"`
    State            string      `json:"state"`
    Zip              json.Number `json:"zip"`
    IsPrimaryAddress string      `json:"isPrimaryAddress"`
}

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

如果您需要自己在没有嵌套结构的情况下执行此操作,您可以使用与 json.Number 相同的方式声明类型,并将 string 作为基础类型

type ZipWrapper string

func (w *ZipWrapper) UnmarshalJSON(data []byte) (err error) {
    if len(data) > 1 && data[0] == '"' && data[len(data)-1] == '"' {
        data = data[1 : len(data)-1]
    }

    if _, err := strconv.Atoi(string(data)); err != nil {
        return err
    }
    *w = ZipWrapper(string(data))
    return nil
}

关于json - Go:解码具有多种类型的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44057958/

相关文章:

json - 如何读取 Apache NiFi 中的属性值

java - Android 版 Gson

python - 传递 Python 元组代替 C++ 结构函数参数是否对性能有影响?

arrays - 如何使用 Golang 将数据放入结构中?

mysql - 在 MySql 中存储可搜索的 JSon

javascript - 如何使用 Meteor 进行 API 调用并将 header 传递给它

xml - 如何将 XML 属性添加到 Go 中的元素?

matlab - 在结构体元胞数组中查找值

go - 从 gorm 模型创建主键时出现问题

closures - 什么时候在 Go 中使用匿名函数?