转到:使用多种类型解组JSON [英] Go: Unmarshalling JSON with multiple types

查看:172
本文介绍了转到:使用多种类型解组JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

结构:

 类型CustomerAddress结构{
Line1字符串`json:line1`
城市字符串`json:city`
国家字符串`json:state`
邮编字符串`json:zip`
IsPrimaryAddress字符串`json:isPrimaryAddress`
}

示例Json:

 地址:[
{
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
}
]

作为一种尝试,我尝试使用

 类型CustomerAddress结构{
Line1字符串`json:line1`
城市字符串` json:city`
国家字符串`json:state`
Zip ZipWrapper`json:zip`
IsPrimaryAddress字符串`json:isPrimaryAddress`
}

类型ZipWrapper结构{
Zip字符串
}

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

如果使用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 noob,并没有完全包装我的头像Unmarshalling如何工作。

解决方案

json 包提供

 输入CustomerAddress struct {
Line1字符串`json:line1`
城市字符串`json:city`
国家字符串`json:state`
Zip json.Number`json:zip`
IsPrimaryAddress字符串`json:isPrimaryAddress``
}

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



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

 类型ZipWrapper字符串

func(w * ZipWrapper)UnmarshalJSON(data [] byte)(err error){
if len(data)> 1&& data [0] =='''&& amp; 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
}


I'm having an issue unmarshalling a JSON response into a struct. The problem I'm having is that the zip code can either return as a string or an integer. How do I write an unmarshal method to check if the zip is an int and force it to store it as a string?

Struct:

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

Example Json:

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

After unmarshalling, the result should have the zip successfully converted into a string:

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

As an attempt, I tried to use a 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)
}

This almost worked except the zip is now a nested struct within CustomerAddress which is not what I want:

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

Any ideas? I feel like this is a relatively easy task but I'm a complete Go noob and haven't fully wrapped my head around how Unmarshalling works.

解决方案

The json package provides the json.Number type to do this:

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

If you needed to do this yourself without the nested struct, you can declare the type the same way as json.Number, with string as the underlying type

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆