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

Go如何接收JSON字符串输入 校验后按条件转换为目标对象

需求说明

需要将结构体AddEndpointRequest中的DefaultResponse字段先以字符串类型接收,校验字段内容是否为合法JSON后,再映射到对应的JSON结构体。
初始使用的结构体定义如下:

type AddEndpointRequest struct {
    Method            string `json:"method"`
    ContentType       int    `json:"contentType"`
    DefaultStatusCode int    `json:"defaultStatusCode"`
    DefaultResponse   string `json:"defaultResponse"`
}

遇到的问题

尝试多种实现方案均无法正常运行,对应报错如下:

  • 传入参数"defaultResponse":{"title":"Buy cheese and bread for breakfast."}时,报错:json: cannot unmarshal object into Go struct field AddEndpointRequest.defaultResponse of type string
  • 定义body为{"method":"GET","contentType":1,"defaultWaitTimeInMillis":100,"defaultStatusCode":200,"defaultResponse":"[{"p":"k"}]"}时,报错:invalid character 'p' after object key:value pair
  • 尝试用反引号拼接嵌套JSON定义body时,出现Go语法错误:./prog.go:21:117: syntax error: unexpected { at end of statement
  • 尝试加斜杠转义嵌套JSON定义body时,出现Go语法错误:./prog.go:21:130: syntax error: unexpected literal "}" at end of statement
  • 其余多种写法也均未解决问题。

问题原因
  • JSON类型不匹配:当请求中defaultResponse传的是对象、数组等非字符串类型JSON值时,Go标准库encoding/json默认不支持直接反序列化到string类型字段,会抛出类型不匹配错误。
  • JSON格式错误:手写JSON字符串时,字符串值内部的双引号未做转义,会导致JSON解析器提前判定字符串结束,后续内容解析失败。
  • Go语法错误:使用反引号定义原始字符串时,若拼接逻辑不合法、或未正确处理特殊字符,会触发编译阶段的语法错误。

解决方案

通过自定义JSON反序列化类型,实现任意JSON值到字符串的接收,同时保留合法性校验、二次映射能力,避免手写JSON转义问题。

完整实现代码

package main

import (
	"encoding/json"
	"fmt"
)

// RawJSONString 支持接收任意合法JSON值,存储为原始字符串格式
type RawJSONString string

// UnmarshalJSON 实现自定义反序列化逻辑,直接存储原始JSON字节
func (s *RawJSONString) UnmarshalJSON(data []byte) error {
	*s = RawJSONString(data)
	return nil
}

// IsValidJSON 校验当前存储内容是否为合法JSON
func (s RawJSONString) IsValidJSON() bool {
	return json.Valid([]byte(s))
}

// 修改后的请求结构体,DefaultResponse使用自定义类型
type AddEndpointRequest struct {
	Method            string        `json:"method"`
	ContentType       int           `json:"contentType"`
	DefaultStatusCode int           `json:"defaultStatusCode"`
	DefaultResponse   RawJSONString `json:"defaultResponse"`
}

func main() {
	// 示例1:defaultResponse传JSON对象
	body1 := `{"method":"GET","contentType":1,"defaultStatusCode":200,"defaultResponse":{"title":"Buy cheese and bread for breakfast."}}`
	var req1 AddEndpointRequest
	if err := json.Unmarshal([]byte(body1), &req1); err != nil {
		panic(err)
	}
	fmt.Println("=== 传JSON对象场景 ===")
	fmt.Printf("原始字符串内容: %s\n", req1.DefaultResponse)
	fmt.Printf("是否为合法JSON: %v\n", req1.DefaultResponse.IsValidJSON())
	// 二次映射到对应结构体
	type RespStruct struct {
		Title string `json:"title"`
	}
	var data1 RespStruct
	if err := json.Unmarshal([]byte(req1.DefaultResponse), &data1); err != nil {
		panic(err)
	}
	fmt.Printf("二次映射结果: %+v\n\n", data1)

	// 示例2:defaultResponse传JSON数组
	body2 := `{"method":"GET","contentType":1,"defaultStatusCode":200,"defaultResponse":[{"p":"k"}]}`
	var req2 AddEndpointRequest
	if err := json.Unmarshal([]byte(body2), &req2); err != nil {
		panic(err)
	}
	fmt.Println("=== 传JSON数组场景 ===")
	fmt.Printf("原始字符串内容: %s\n", req2.DefaultResponse)
	fmt.Printf("是否为合法JSON: %v\n", req2.DefaultResponse.IsValidJSON())
	// 二次映射到切片
	var data2 []map[string]string
	if err := json.Unmarshal([]byte(req2.DefaultResponse), &data2); err != nil {
		panic(err)
	}
	fmt.Printf("二次映射结果: %+v\n", data2)
}

注意事项

  • 若需要将JSON内容作为字符串值传递(而非直接传对象/数组),手写JSON时必须对字符串内部的双引号做转义,例如"defaultResponse":"[{\"p\":\"k\"}]",否则会触发JSON解析错误。
  • 尽量避免手写拼接JSON字符串,优先通过结构体序列化生成请求体,可以彻底避免转义类错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:21:40