【问题标题】:Handling request body with different types [duplicate]处理不同类型的请求正文[重复]
【发布时间】:2020-03-02 15:04:29
【问题描述】:

假设后端应用程序有这样的请求。如您所见,这是一个对象数组。

[
    {
        "section_id": "8ad1f7cc-a510-48ee-b4fa-bedbee444a84", // (uuid - string)
        "section_name": "First section"
    },
    {
        "section_id": 1556895, // (int)
        "section_name": "Second section"
    }
]

我想解析这个数组。根据部分 id 类型,应用程序需要做不同的事情。如何绕过严格类型?

requestBody, err := ioutil.ReadAll(request.Body)

if err = json.Unmarshal([]byte(requestBody), &sections); err != nil {
    println(err)
}

for _, section := range sections {
    if reflect.TypeOf(section.ID) == string {
        // block 1
    } reflect.TypeOf(section.ID) == int {
        // block 2
    }
}

【问题讨论】:

标签: json go reflection


【解决方案1】:

你可以试试这个:

type section struct {
    ID interface{} `json:"section_id"`
    Name string `json:"section_name"`
}

dec := json.NewDecoder(requestBody)
dec.UseNumber()
var sections []section
if err := dec.Decode([]byte(request.Body), &sections); err != nil {
    println(err)
}

for _, section := range sections {
    if reflect.TypeOf(section.ID).String() == "string" {
        // block 1
    } reflect.TypeOf(section.ID).String() == "json.Number" {
        n := section.ID.Int64()
        // block 2
    }
}

【讨论】:

  • 感谢您的回答。这里唯一的错误是您检查 id 类型的部分。我将其更改为if reflect.TypeOf(section.ID).String() == "string" 等。我还注意到1556895 值返回float64 类型。我想它一定是int。好奇怪。
  • 关于float64,当类型为interface{} 时,数字默认会发生这种情况。 JSON解码器上有一个UseNumber()选项,可以将数字保存为json.Number,以后可以转换。
  • 我在这部分代码中有这样的错误Cannot use requestBody (type []byte) as type io.Readorjson.NewDecoder(requestBody)
  • 不要使用requestBody,只使用request.Body
【解决方案2】:

有几种方法可以做到这一点:

type Section struct {
   ID interface{} `json:"section_id"`
   SectionName string `json:"section_name"
}

for _, section := range sections {
   if str,ok:=section.ID.(string); ok {
   } else if number, ok:=section.ID.(float64); ok {
   }
}

或者:

type Section struct {
   ID json.RawMessage `json:"section_id"`
   SectionName string `json:"section_name"
}

for _, section := range sections {
   if value, err:=strconv.Atoi(string(section.ID)); err==nil {

   } else {
   }
}

【讨论】:

  • 感谢您的回答。我测试了你的第一个变体。为什么设置float64 而不是int?在我的示例中,1556895int,对吧?
  • stdlib json unmarshaler 将所有数字解组为 float64。您可以改用json.Decoder,调用decoder.UseNumber(),并获取json.Number 值而不是float64。
  • 我能再问你一个问题吗?!如何将int 转换为json.RawMessage?我需要将int 值设置为Section 结构的ID 字段。
  • section.ID=json.RawMessage(json.Marshal(value)) 适用于所有类型的值。
猜你喜欢
  • 2013-09-02
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 2019-08-02
相关资源
最近更新 更多