You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言API响应JSON反序列化:空字符串字段兼容问题

解决Go中JSON反序列化子结构体与空字符串不兼容的问题

问题的核心是API返回的字段类型不一致:有数据时是JSON对象,无数据时是空字符串,而Go标准库的JSON解析器无法自动将字符串转换为结构体类型,哪怕用指针或omitempty标签也不行——omitempty仅影响序列化时的零值忽略,指针则期望输入是null而非字符串。

解决方案:为子结构体实现自定义UnmarshalJSON方法

通过自定义反序列化逻辑,让结构体既能处理JSON对象,也能处理空字符串(甚至null)的情况。

1. 定义子结构体并实现自定义反序列化

以CaseReport为例,PrimaryContact可以复用同样的逻辑:

package main

import (
    "encoding/json"
    "fmt"
)

type CaseReport struct {
    ReportID string `json:"report_id"`
    Content  string `json:"content"`
}

// 自定义UnmarshalJSON,处理空字符串和对象两种输入
func (cr *CaseReport) UnmarshalJSON(data []byte) error {
    inputStr := string(data)
    // 处理空字符串或null的情况
    if inputStr == `""` || inputStr == "null" {
        *cr = CaseReport{} // 置为零值结构体
        return nil
    }
    // 用别名避免递归调用当前UnmarshalJSON方法
    type Alias CaseReport
    return json.Unmarshal(data, (*Alias)(cr))
}

// 主响应结构体
type APIResponse struct {
    Result struct {
        PrimaryContact CaseReport `json:"primary_contact"`
        CaseReport     CaseReport `json:"case_report"`
    } `json:"result"`
}

2. 测试两种场景

  • 场景1:有数据的API响应
func main() {
    // 模拟有数据的响应
    validResp := `{
        "result": {
            "primary_contact": {"report_id": "C001", "content": "John Doe"},
            "case_report": {"report_id": "R001", "content": "Lost item report"}
        }
    }`

    var resp1 APIResponse
    if err := json.Unmarshal([]byte(validResp), &resp1); err != nil {
        fmt.Println("解析有数据响应失败:", err)
        return
    }
    fmt.Printf("有数据时的CaseReport: %+v\n", resp1.Result.CaseReport)
}
  • 场景2:无数据的API响应
func main() {
    // 模拟无数据的响应(空字符串)
    emptyResp := `{
        "result": {
            "primary_contact": "",
            "case_report": ""
        }
    }`

    var resp2 APIResponse
    if err := json.Unmarshal([]byte(emptyResp), &resp2); err != nil {
        fmt.Println("解析空字符串响应失败:", err)
        return
    }
    fmt.Printf("空字符串时的CaseReport: %+v\n", resp2.Result.CaseReport)
}

为什么之前的方法无效?

  • omitempty标签:仅在序列化结构体时忽略零值字段,对反序列化没有作用。
  • 子结构体设为指针:Go的JSON解析器仅会将null转换为nil指针,但无法处理空字符串"",因此仍会抛出类型不匹配的错误。

内容的提问来源于stack exchange,提问作者Maria Villanueva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:25:14