2 回答
TA贡献1810条经验 获得超4个赞
我不知道这是否是一个好的解决方案,我还是新手,但无论如何,你可以使用json。RawMessage并将财产的解封“延迟”到两个单独的结构字段之一。例如:wlan
package main
import (
"encoding/json"
"fmt"
)
// Data contains data about the Fritz!Box. (other fields omitted for brevity)
type Data struct {
Language string `json:"language"`
NewsURL string `json:"NEWSLETTER_URL"`
WLanRaw *json.RawMessage `json:"wlan"`
WLanBool bool `json:"-"`
WLanInfo *WLanInfo `json:"-"`
}
// WLanInfo contains infos about the Wireless Lan
type WLanInfo struct {
Txt string `json:"txt"`
Led string `json:"led"`
Title string `json:"title"`
Link string `json:"link"`
Tooltip string `json:"tooltip"`
}
func UnmarshalData(raw []byte, data *Data) error {
if err := json.Unmarshal(raw, data); err != nil {
return err
}
switch string(*data.WLanRaw) {
case "true", "false":
json.Unmarshal(*data.WLanRaw, &data.WLanBool)
default:
if err := json.Unmarshal(*data.WLanRaw, &data.WLanInfo); err != nil {
return err
}
}
return nil
}
func main() {
jsonBool := []byte(`
{
"language": "it",
"NEWSLETTER_URL": "https://example.com/news",
"wlan": true
}`)
jsonInfo := []byte(`
{
"language": "it",
"NEWSLETTER_URL": "https://example.com/news",
"wlan": {
"txt": "footxt",
"led": "fooled",
"title": "hello",
"link": "bar",
"tooltip": "baz"
}
}`)
// error handling omitted
var dataBool Data
UnmarshalData(jsonBool, &dataBool)
fmt.Printf("%+v\n\n", dataBool)
var dataInfo Data
UnmarshalData(jsonInfo, &dataInfo)
fmt.Printf("%+v %+v\n", dataInfo, dataInfo.WLanInfo)
}
$ go build fritz.go
$ ./fritz
{Language:it NewsURL:https://example.com/news WLanRaw:0xc0000a4060 WLanBool:true WLanInfo:<nil>}
{Language:it NewsURL:https://example.com/news WLanRaw:0xc0000a4080 WLanBool:false WLanInfo:0xc0000b0000} &{Txt:footxt Led:fooled Title:hello Link:bar Tooltip:baz}
$
TA贡献1830条经验 获得超3个赞
你可以实现 json。Unmarshaler 和 json.封送线接口。
type WLan struct {
Bool *bool `json:"-"`
Txt string `json:"txt"`
Led string `json:"led"`
Title string `json:"title"`
Link string `json:"link"`
Tooltip string `json:"tooltip"`
}
// implements json.Unmarshaler
func (w *WLan) UnmarshalJSON(data []byte) error {
if len(data) > 0 && (data[0] == 't' || data[0] == 'f') { // seems to be a bool
w.Bool = new(bool)
return json.Unmarshal(data, w.Bool)
}
if len(data) > 1 && data[0] == '{' && data[len(data)-1] == '}' { // it's an object
// type W and the conversion (*W)(w) are required to
// prevent encoding/json from invoking the UnmarshalJSON
// method recursively causing a stack overflow
type W WLan
return json.Unmarshal(data, (*W)(w))
}
return nil // or error, up to you
}
// implements json.Marshaler
func (w WLan) MarshalJSON() ([]byte, error) {
if w.Bool != nil {
return json.Marshal(*w.Bool)
}
// Same as with UnmarshalJSON, type W and the conversion W(w) are
// required to prevent encoding/json from invoking the MarshalJSON
// method recursively causing a stack overflow
type W WLan
return json.Marshal(W(w))
}
https://play.golang.org/p/s72zt4ny7Pv
- 2 回答
- 0 关注
- 89 浏览
添加回答
举报