使用
json.RawMessage 来捕获不确定的字段。
使用 json 中的“-”名称来隐藏
DisplayName
字段,以便解码器忽略它。应用程序将在解码顶层 JSON 后填充此字段。
type MyListItem struct {
Date string `json:"date"`
RawDisplayName json.RawMessage `json:"display_name"`
DisplayName []string `json:"-"`
}
解析顶层JSON:
var li MyListItem
if err := json.Unmarshal(data, &li); err != nil {
}
根据原始数据的类型解析显示名称:
if len(li.RawDisplayName) > 0 {
switch li.RawDisplayName[0] {
case '"':
if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil {
}
case '[':
var s []string
if err := json.Unmarshal(li.RawDisplayName, &s); err != nil {
}
li.DisplayName = strings.Join(s, "&")
}
}
playground 示例
将上述内容合并到for循环中以处理MyListings
:
var listings MyListings
if err := json.Unmarshal([]byte(data), &listings); err != nil {
}
for i := range listings.CLItems {
li := &listings.CLItems[i]
if len(li.RawDisplayName) > 0 {
switch li.RawDisplayName[0] {
case '"':
if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil {
}
case '[':
var s []string
if err := json.Unmarshal(li.RawDisplayName, &s); err != nil {
}
li.DisplayName = strings.Join(s, "&")
}
}
}
示例
如果数据模型中有一个值可以是字符串或字符串切片,则将逻辑封装在类型中会很有帮助。在实现json.Unmarshaler接口时解析JSON数据。
type multiString string
func (ms *multiString) UnmarshalJSON(data []byte) error {
if len(data) > 0 {
switch data[0] {
case '"':
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString(s)
case '[':
var s []string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString(strings.Join(s, "&"))
}
}
return nil
}
使用方法如下:
type MyListItem struct {
Date string `json:"date"`
DisplayName multiString `json:"display_name"`
}
type MyListings struct {
CLItems []MyListItem `json:"myitems"`
}
var listings MyListings
if err := json.Unmarshal([]byte(data), &listings); err != nil {
log.Fatal(err)
}
示例程序
以下代码可以将值作为字符串切片获取,而不是使用 & 连接的单个字符串。
type multiString []string
func (ms *multiString) UnmarshalJSON(data []byte) error {
if len(data) > 0 {
switch data[0] {
case '"':
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString{s}
case '[':
if err := json.Unmarshal(data, (*[]string)(ms)); err != nil {
return err
}
}
}
return nil
}
Playground example.
DisplayName
应该是什么类型? - zerkms