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

brgchamk  于 2024-01-04  发布在  Go
关注(0)|答案(4)|浏览(137)

当我对REST API进行HTTP调用时,我可能会以Number或String的形式返回JSON值count。我想在两种情况下将其封送为整数。我如何在Go中处理这个问题?

mcdcgff0

mcdcgff01#

使用“string”字段标记选项指定字符串应转换为数字。该选项的文档是:
“string”选项表示字段在JSON编码的字符串中存储为JSON。它仅适用于字符串,浮点,整数或布尔类型的字段。这种额外的编码级别有时在与JavaScript程序通信时使用:
以下是一个用途:

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

字符串
playground example
如果JSON值可以是number或string,则解组到interface{}并在解组后转换为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
    }
    return c, nil
  default:
    return 0, fmt.Errorf("conversion to int from %T not supported", v)
  }
}

brtdzjyr

brtdzjyr2#

// 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
}

字符串

9gm1akwq

9gm1akwq3#

我遇到了同样的问题,一个值列表的值是字符串或结构。我使用的解决方案是创建一个helper结构,其中包含预期类型的字段,并将值解析为正确的字段。

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{},因为它明确地说明了开发人员的期望。

xqkwcwgp

xqkwcwgp4#

go标准库“json/encoding”提供了一个json.Number类型,用于解析JSON数据中的字符串数字和整数。
以下是一个用途:

type Foo struct {
    Value json.Number `json:"value"`
}

字符串
json.Number实际上是string的别名,json.Unmarshal在解组时专门处理它,以支持两种格式,如“123”和123。
一旦你有了一个json.Number,你可以根据需要使用.Int64().Float64()方法来提取它的数值表示。
playground example

package main

import (
    "encoding/json"
    "fmt"
)

type Foo struct {
    Value json.Number `json:"value"`
}

func main() {
    // json int -> json.Number
    var foo Foo
    if err := json.Unmarshal([]byte(`{"value": 123}`), &foo); err != nil {
        fmt.Println("json unmarshal err:", err)
        return
    }
    fmt.Printf("foo: %+v\n", foo)

    // json string -> json.Number
    var foo2 Foo
    if err := json.Unmarshal([]byte(`{"value": "123"}`), &foo2); err != nil {
        fmt.Println("json unmarshal err:", err)
        return
    }
    fmt.Printf("foo2: %+v\n", foo2)

    // json.Number -> int64
    intValue, err := foo.Value.Int64()
    if err != nil {
        fmt.Println("value.Int64() err:", err)
        return
    }

    fmt.Println("intValue:", intValue)
}


产出:

foo: {Value:123}
foo2: {Value:123}
intValue: 123

相关问题