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

Go语言嵌套JSON解析问题:字符串化嵌套JSON无法Unmarshal

兼容两种嵌套JSON格式的Go解析方案

嗨,这个问题我之前也碰到过!默认的json.Unmarshal对类型匹配要求很严格,当你的Data字段在JSON里是字符串化的JSON时,因为和结构体里的map[string]interface{}类型不匹配,就会解析失败导致Data为空。要兼容两种情况,我们可以通过自定义UnmarshalJSON方法来实现灵活解析。

解决方案代码

直接给你上可运行的实现:

package main

import (
	"encoding/json"
	"fmt"
)

type atomRequest struct {
	Stream string                 `json:"stream"`
	Data   map[string]interface{} `json:"data"`
}

// 自定义JSON反序列化方法,兼容对象和字符串化JSON两种格式
func (a *atomRequest) UnmarshalJSON(data []byte) error {
	// 定义临时结构体,用json.RawMessage保留Data字段的原始JSON字节
	type tempRequest struct {
		Stream string          `json:"stream"`
		Data   json.RawMessage `json:"data"`
	}

	var temp tempRequest
	if err := json.Unmarshal(data, &temp); err != nil {
		return fmt.Errorf("failed to unmarshal temp struct: %w", err)
	}

	// 先赋值Stream字段
	a.Stream = temp.Stream

	// 第一种情况:尝试直接把Data解析成map
	var dataMap map[string]interface{}
	if err := json.Unmarshal(temp.Data, &dataMap); err == nil {
		a.Data = dataMap
		return nil
	}

	// 第二种情况:如果直接解析失败,尝试先解析成字符串,再把字符串内容解析成map
	var dataStr string
	if err := json.Unmarshal(temp.Data, &dataStr); err != nil {
		return fmt.Errorf("data is neither object nor string: %w", err)
	}

	if err := json.Unmarshal([]byte(dataStr), &dataMap); err != nil {
		return fmt.Errorf("failed to unmarshal stringified JSON: %w", err)
	}
	a.Data = dataMap
	return nil
}

// 测试示例
func main() {
	// 测试1:正常的嵌套JSON对象
	json1 := []byte(`{"stream":"test1","data":{"name":"ohad","age":30}}`)
	var req1 atomRequest
	if err := json.Unmarshal(json1, &req1); err != nil {
		fmt.Printf("Error parsing json1: %v\n", err)
	} else {
		fmt.Printf("Parsed json1: %+v\n", req1)
	}

	// 测试2:字符串化的嵌套JSON
	json2 := []byte(`{"stream":"test2","data":"{\"name\":\"ohad\",\"age\":30}"}`)
	var req2 atomRequest
	if err := json.Unmarshal(json2, &req2); err != nil {
		fmt.Printf("Error parsing json2: %v\n", err)
	} else {
		fmt.Printf("Parsed json2: %+v\n", req2)
	}
}

代码逻辑说明

  1. 临时结构体+RawMessage:用json.RawMessage接收Data字段,这样可以保留原始的JSON字节,而不会被自动解析成错误类型。
  2. 先尝试直接解析:先把RawMessage直接解析成map[string]interface{},如果成功,说明是正常的嵌套JSON对象,直接赋值即可。
  3. Fallback到字符串解析:如果直接解析失败,说明Data是字符串类型,先把它解析成字符串,再将这个字符串的内容二次解析成map。

边界情况处理

  • 如果Data是null,会直接解析成nil的map,符合预期。
  • 如果字符串化的JSON格式无效,会返回明确的错误,方便你排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:30:38