如何解析既可为字符串又可为字符串数组的不一致JSON字段?
解决JSON字段类型不一致的解析问题
这个问题在处理第三方不可控的JSON数据时特别常见——字段类型偶尔“跳变”,导致标准的json.Unmarshal直接报错。下面分两种常见场景给你解决方案:
场景1:单个字段(比如date)偶尔从字符串变成数组
如果是某个具体字段(比如你的Date)大部分时候是字符串,偶尔变成单元素数组,我们可以给这个字段定义自定义类型并实现UnmarshalJSON方法,自动兼容两种格式:
步骤1:定义自定义类型并实现解析逻辑
import "encoding/json" // 自定义类型,兼容字符串和单元素数组 type StringOrArray string func (s *StringOrArray) UnmarshalJSON(data []byte) error { // 先尝试按普通字符串解析 var str string if err := json.Unmarshal(data, &str); err == nil { *s = StringOrArray(str) return nil } // 字符串解析失败,尝试按字符串数组解析 var strArr []string if err := json.Unmarshal(data, &strArr); err != nil { return err } // 取数组第一个元素(如果数组非空),否则设为空字符串 if len(strArr) > 0 { *s = StringOrArray(strArr[0]) } else { *s = StringOrArray("") } return nil }
步骤2:修改结构体字段类型
把MyListItem里的Date字段类型替换成我们的自定义类型:
type MyListItem struct { Date StringOrArray `json:"date"` DisplayName string `json:"display_name"` }
之后再用原来的解析代码就可以了——不管date是"30 Apr"还是["30 Apr"],都能正常解析成字符串形式的Date。
场景2:数组字段(比如myitems)偶尔变成单个对象
如果是myitems字段大部分时候是数组,偶尔变成单个MyListItem对象,我们需要给MyListings结构体实现UnmarshalJSON方法:
func (m *MyListings) UnmarshalJSON(data []byte) error { // 先尝试按原始结构体(数组形式)解析 type TempMyListings MyListings var temp TempMyListings if err := json.Unmarshal(data, &temp); err == nil { *m = MyListings(temp) return nil } // 数组解析失败,尝试按单个对象解析,再包装成数组 var singleItem MyListItem if err := json.Unmarshal(data, &singleItem); err != nil { return err } m.CLItems = []MyListItem{singleItem} return nil }
这样当JSON里的myitems是单个对象时,会自动把它转成包含该对象的数组,完美兼容两种格式。
额外提示
如果数组里有多个元素(比如date偶尔是多元素数组),你可以根据业务需求调整自定义解析逻辑——比如取第一个元素、拼接所有元素,或者直接把数组存下来(这时候自定义类型可以改成[]string,然后兼容字符串转单元素数组)。
内容的提问来源于stack exchange,提问作者John F
相关产品推荐
相关产品推荐

