使用 json.RawMessage 解组 json 结构
Unmarshalling json to structure using json.RawMessage
我需要解组 json 可能具有以下格式的对象:
格式 1:
{
"contactType": 2,
"value": "0123456789"
}
格式 2:
{
"contactType": "MobileNumber",
"value": "0123456789"
}
我用于解组的结构是:-
type Contact struct {
ContactType int `json:"contactType"`
Value string `json:"value"`
}
但这仅适用于格式 1。我不想更改 ContactType 的数据类型,但我也想适应第二种格式。我听说过 json.RawMarshal 并尝试使用它。
type Contact struct {
ContactType int
Value string `json:"value"`
Type json.RawMessage `json:"contactType"`
}
type StringContact struct {
Type string `json:"contactType"`
}
type IntContact struct {
Type int `json:"contactType"`
}
这完成了解组,但我无法设置 ContactType
变量,这取决于 json.RawMessage
的类型。如何为我的结构建模以解决此问题?
您需要自己进行解组。有一篇非常好的文章展示了如何使用 json.RawMessage 权限以及针对这个问题的许多其他解决方案,例如使用接口、RawMessage、实现您自己的解组和解码功能等。
您将在此处找到这篇文章:JSON decoding in GO by Attila Oláh
注意:Attila 在他的代码示例中犯了一些错误。
我冒昧地(使用 Attila 的一些代码)组合了一个使用 RawMessage 延迟解组的工作示例,这样我们就可以在我们自己的解码函数版本上完成它。
package main
import (
"fmt"
"encoding/json"
"io"
)
type Record struct {
AuthorRaw json.RawMessage `json:"author"`
Title string `json:"title"`
URL string `json:"url"`
Author Author
}
type Author struct {
ID uint64 `json:"id"`
Email string `json:"email"`
}
func Decode(r io.Reader) (x *Record, err error) {
x = new(Record)
if err = json.NewDecoder(r).Decode(x); err != nil {
return
}
if err = json.Unmarshal(x.AuthorRaw, &x.Author); err == nil {
return
}
var s string
if err = json.Unmarshal(x.AuthorRaw, &s); err == nil {
x.Author.Email = s
return
}
var n uint64
if err = json.Unmarshal(x.AuthorRaw, &n); err == nil {
x.Author.ID = n
}
return
}
func main() {
byt_1 := []byte(`{"author": 2,"title": "some things","url": "https://whosebug.com"}`)
byt_2 := []byte(`{"author": "Mad Scientist","title": "some things","url": "https://whosebug.com"}`)
var dat Record
if err := json.Unmarshal(byt_1, &dat); err != nil {
panic(err)
}
fmt.Printf("%#s\r\n", dat)
if err := json.Unmarshal(byt_2, &dat); err != nil {
panic(err)
}
fmt.Printf("%#s\r\n", dat)
}
希望对您有所帮助。
我需要解组 json 可能具有以下格式的对象:
格式 1:
{
"contactType": 2,
"value": "0123456789"
}
格式 2:
{
"contactType": "MobileNumber",
"value": "0123456789"
}
我用于解组的结构是:-
type Contact struct {
ContactType int `json:"contactType"`
Value string `json:"value"`
}
但这仅适用于格式 1。我不想更改 ContactType 的数据类型,但我也想适应第二种格式。我听说过 json.RawMarshal 并尝试使用它。
type Contact struct {
ContactType int
Value string `json:"value"`
Type json.RawMessage `json:"contactType"`
}
type StringContact struct {
Type string `json:"contactType"`
}
type IntContact struct {
Type int `json:"contactType"`
}
这完成了解组,但我无法设置 ContactType
变量,这取决于 json.RawMessage
的类型。如何为我的结构建模以解决此问题?
您需要自己进行解组。有一篇非常好的文章展示了如何使用 json.RawMessage 权限以及针对这个问题的许多其他解决方案,例如使用接口、RawMessage、实现您自己的解组和解码功能等。
您将在此处找到这篇文章:JSON decoding in GO by Attila Oláh 注意:Attila 在他的代码示例中犯了一些错误。
我冒昧地(使用 Attila 的一些代码)组合了一个使用 RawMessage 延迟解组的工作示例,这样我们就可以在我们自己的解码函数版本上完成它。
package main
import (
"fmt"
"encoding/json"
"io"
)
type Record struct {
AuthorRaw json.RawMessage `json:"author"`
Title string `json:"title"`
URL string `json:"url"`
Author Author
}
type Author struct {
ID uint64 `json:"id"`
Email string `json:"email"`
}
func Decode(r io.Reader) (x *Record, err error) {
x = new(Record)
if err = json.NewDecoder(r).Decode(x); err != nil {
return
}
if err = json.Unmarshal(x.AuthorRaw, &x.Author); err == nil {
return
}
var s string
if err = json.Unmarshal(x.AuthorRaw, &s); err == nil {
x.Author.Email = s
return
}
var n uint64
if err = json.Unmarshal(x.AuthorRaw, &n); err == nil {
x.Author.ID = n
}
return
}
func main() {
byt_1 := []byte(`{"author": 2,"title": "some things","url": "https://whosebug.com"}`)
byt_2 := []byte(`{"author": "Mad Scientist","title": "some things","url": "https://whosebug.com"}`)
var dat Record
if err := json.Unmarshal(byt_1, &dat); err != nil {
panic(err)
}
fmt.Printf("%#s\r\n", dat)
if err := json.Unmarshal(byt_2, &dat); err != nil {
panic(err)
}
fmt.Printf("%#s\r\n", dat)
}
希望对您有所帮助。