如何解析包含不同类型元素的JSON-RPC中的key数组?
解决Go中JSON混合类型数组的解析问题
针对你遇到的JSON-RPC响应中key数组包含字符串、整数混合类型的解析问题,提供两种可行方案:
方案一:用[]interface{}临时接收,手动转换类型
这种方式简单直接,适合快速实现,但需要手动处理类型断言,若JSON结构不符合预期会引发运行时错误:
修改JsonRpcEntry的Key字段定义:
type JsonRpcEntry struct { Key []interface{} `json:"key"` Val JsonRpcEntry_Val `json:"val"` }
解析完成后手动转换每个元素的类型:
// 遍历entries处理每个key for _, entry := range entries { // 断言第一个元素为字符串 str1, ok := entry.Key[0].(string) if !ok { // 处理类型不匹配错误 } // JSON数字默认解析为float64,转换为int numFloat, ok := entry.Key[1].(float64) intNum := int(numFloat) if !ok { // 处理类型不匹配错误 } // 断言第三个元素为字符串 str2, ok := entry.Key[2].(string) if !ok { // 处理类型不匹配错误 } // 后续使用str1、intNum、str2即可 }
方案二:自定义类型实现UnmarshalJSON,严格校验结构
这种方式更严谨,能在解析阶段就校验key数组的结构和类型,避免后续类型断言的繁琐:
- 定义对应
key结构的自定义类型:
type KeyTuple struct { Str1 string Num int Str2 string }
- 为
KeyTuple实现UnmarshalJSON方法:
import "fmt" import "encoding/json" func (kt *KeyTuple) UnmarshalJSON(data []byte) error { var arr []interface{} if err := json.Unmarshal(data, &arr); err != nil { return err } // 校验数组长度是否为3 if len(arr) != 3 { return fmt.Errorf("key数组长度必须为3") } // 解析第一个元素为字符串 var ok bool kt.Str1, ok = arr[0].(string) if !ok { return fmt.Errorf("key第一个元素必须是字符串") } // 解析第二个元素为整数(JSON数字默认是float64,需转换) numFloat, ok := arr[1].(float64) if !ok { return fmt.Errorf("key第二个元素必须是整数") } kt.Num = int(numFloat) // 解析第三个元素为字符串 kt.Str2, ok = arr[2].(string) if !ok { return fmt.Errorf("key第三个元素必须是字符串") } return nil }
- 修改
JsonRpcEntry的Key字段为自定义类型:
type JsonRpcEntry struct { Key KeyTuple `json:"key"` Val JsonRpcEntry_Val `json:"val"` }
- 正常解析即可,解析过程中会自动校验类型:
jsonResult := JsonRpcRsp{} if err := json.Unmarshal(data, &jsonResult); err != nil { // 处理解析错误 } entries := []JsonRpcEntry{} if err := json.Unmarshal(jsonResult.Result, &entries); err != nil { // 处理解析错误(比如key结构不符合要求) } // 直接使用entries中每个entry的Key.Str1、Key.Num、Key.Str2
另外注意你原代码中的循环错误:for _, val := range jsonResult是错误的,因为jsonResult是结构体而非数组,正确做法是直接对jsonResult.Result进行反序列化,如上述代码所示。
内容的提问来源于stack exchange,提问作者ipStack
相关产品推荐
相关产品推荐

