解码JSON值,可以是字符串或数字

时间:2017-12-07 03:44:35

标签: json go

当我对REST API进行HTTP调用时,我可能会将JSON值count作为数字或字符串返回。在任何一种情况下,我都想把它整理成一个整数。我怎么能在Go中处理这个问题?。

3 个答案:

答案 0 :(得分:8)

使用"字符串"字段标记选项,指定应将字符串转换为数字。该选项的documentation为:

  

"字符串"选项表示字段在JSON编码的字符串中存储为JSON。它仅适用于字符串,浮点,整数或布尔类型的字段。在与JavaScript程序通信时,有时会使用这种额外的编码级别:

以下是一个使用示例:

type S struct {
    Count int `json:"count,string"`
}

playground example

如果JSON值可以是数字或字符串,则解组到接口{}并在解组后转换为int:

Count interface{} `json:"count,string"`

使用此函数将interface {}值转换为int:

func getInt(v interface{}) (int, error) {
  switch v := v.(type) {
  case float64:
    return int(v), nil
  case string:
    c, err := strconv.Atoi(v)
    if err != nil {
       return 0, err
    }
  default:
    return 0, fmt.Errorf("conversion to int from %T not supported", v)
  }
}

答案 1 :(得分:0)

// Format of your expected request
type request struct {
    ACTIVE    string `json:"active"`
    CATEGORY  string `json:"category"`
}

// struct to read JSON input
var myReq request 

// Decode the received JSON request to struct
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&myReq)
  if err != nil {
  log.Println( err)
// Handler for invalid JSON received or if you want to decode the request using another struct with int.
  return
}
defer r.Body.Close()

// Convert string to int
numActive, err = strconv.Atoi(myReq.ACTIVE)
if err != nil {
  log.Println(err) 
// Handler for invalid int received
  return
}

// Convert string to int    
numCategory, err = strconv.Atoi(myReq.CATEGORY)
if err != nil {
  log.Println(err)
// Handler for invalid int received
  return
}

答案 2 :(得分:0)

对于值列表,其中值是字符串或结构,我也遇到了同样的问题。我正在使用的解决方案是创建一个具有预期类型的​​字段的辅助结构,并将值解析为正确的字段。

type Flag struct {
    ID   string `json:"id"`
    Type string `json:"type"`
}

type FlagOrString struct {
    Flag   *Flag
    String *string
}

func (f *FlagOrString) UnmarshalJSON(b []byte) error {
    start := []byte("\"")
    for idx := range start {
        if b[idx] != start[idx] {
            return json.Unmarshal(b, &f.Flag)
        }
    }
    return json.Unmarshal(b, &f.String)
}

var MainStruct struct {
    Vals []FlagOrString
}

自定义Unmarshaller简化了代码。我个人更喜欢interface{},因为它明确说明了开发人员的期望。