使用json.RawMessage将json反序列化为结构体

5
我可以帮助您进行翻译。以下是需要翻译的内容:

我需要解析可能具有以下格式的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"`
} 

这样做可以进行取消编组,但我无法设置取决于 json.RawMessage 类型的变量 ContactType。我该如何设计我的结构以解决这个问题?

您可以将类型为“interface”的Contact Type进行设置。 - Jagrati
1个回答

3
您需要自行进行解组。有一篇非常好的文章展示了如何正确使用json.RawMessage以及其他解决此问题的方法,例如使用接口、RawMessage、实现您自己的解组和解码函数等。
您可以在这里找到该文章:Attila Oláh的《JSON解码在GO语言中》注意:Attila在代码示例中犯了一些错误。 我利用Attila的一些代码,组合成一个使用RawMessage的可行示例,延迟解组,以便我们可以在我们自己的版本的Decode函数中进行解组。 GOLANG Playground链接
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://stackoverflow.com"}`)

    byt_2 := []byte(`{"author": "Mad Scientist","title": "some things","url": "https://stackoverflow.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)
}

希望这可以帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接