为了账号安全,请及时绑定邮箱和手机立即绑定

如何解组不同的json格式

如何解组不同的json格式

Go
宝慕林4294392 2022-06-27 15:47:00
我读了很多类似的问题,但还没有找到正确的解决方案。希望有人能给我更好的主意。我的错误响应可能是以下格式之一:var errProxy = `{"errors":{"id": "1", "message": "failed to resolve the ip", "status": "failed"}}`var errServer = `{"errors": "failed to ping the dns server."}`我试图通过使用两个结构来解决这个问题,并尝试一个接一个地解组,直到 err 为 nil 并返回:// ErrorServer and ErrorProxy is my two struct to represent my above two error response.type ErrorServer struct {    Error string `json:"errors"`}type ErrorResponse struct {    ID      string `json:"id"`    Message string `json:"message"`    Status  string `json:"status"`}type ErrorProxy struct {    ErrorResponse}这是我用来解析它的函数:func parseErrorResponse(body io.ReadCloser) (string, error) {    var errServer ErrorServer    var errProxy ErrorProxy    err := json.NewDecoder(body).Decode(&errServer)    if err != nil {        err = json.NewDecoder(body).Decode(&errProxy)        if err != nil {            return "", err        }        return errProxy.Error, nil    }    return errServer.Errors, nil}
查看完整描述

3 回答

?
倚天杖

TA贡献1828条经验 获得超3个赞

我认为自定义解组功能适用于这种情况


type ErrorServer struct {

    Error string

}


type ErrorResponse struct {

    ID      string

    Message string

    Status  string

}

type ErrorProxy struct {

    Err ErrorResponse

}


func parseErrorResponse(body io.Reader) (interface{}, error) {

    data := make(map[string]interface{})

    if err := json.NewDecoder(body).Decode(&data); err != nil {

        return nil, err

    }

    // Check type of errors field

    switch errors := data["errors"].(type) {

    case string:

        // Unmarshal for ErrorServer

        errServer := &ErrorServer{

            Error: errors,

        }

        return errServer, nil

    case map[string]interface{}:

        // Unmarshal for ErrorProxy

        errProxy := &ErrorProxy{

            Err: ErrorResponse{

                ID:      errors["id"].(string),

                Message: errors["message"].(string),

                Status:  errors["status"].(string),

            },

        }

        return errProxy, nil

    default:

        return nil, fmt.Errorf(`failed to parse "errors" field`)

    }

}


func main() {

    body := bytes.NewReader([]byte(`{"errors": "failed to ping the dns server."}`))

    //body := bytes.NewReader([]byte(`{"errors":{"id": "1", "message": "failed to resolve the ip", "status": "failed"}}`))

    

    parsedErr, _ := parseErrorResponse(body)


    switch err := parsedErr.(type) {

    case *ErrorServer:

        fmt.Printf("err server: %+v \n", err)

    case *ErrorProxy:

        fmt.Printf("err response: %+v \n", err)

    }

}


查看完整回答
反对 回复 2022-06-27
?
森林海

TA贡献2011条经验 获得超2个赞

另一种方法是使用类型断言。您可以将该 json 字符串解组为map[string]interface{}并检查该值interface{}是 astring还是map[string]interface{}。取决于它的类型,您知道它是哪种错误并从中构造一个结构。



查看完整回答
反对 回复 2022-06-27
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

有趣的是,我只是在这里给出了这个问题的答案:使用自定义UnmarshalJSON函数。你如何在 Golang 中修改这个结构来接受两个不同的结果?


适用于您的情况:


package main


import (

    "encoding/json"

    "fmt"

    "log"

)


type Answer struct {

    Errors Error `json:"errors"`

}


type ErrorResponse struct {

    ID      string `json:"id"`

    Message string `json:"message"`

    Status  string `json:"status"`

}


type Error struct {

    Error         string

    ErrorResponse ErrorResponse

}


func (s *Error) UnmarshalJSON(b []byte) error {

    if len(b) == 0 {

        // no data, nothing to do

        return nil

    }

    if b[0] == '{' {

        // is object

        return json.Unmarshal(b, &s.ErrorResponse)

    }

    return json.Unmarshal(b, &s.Error)

}


func main() {

    var errProxy = []byte(`{"errors":{"id": "1", "message": "failed to resolve the ip", "status": "failed"}}`)

    var errServer = []byte(`{"errors": "failed to ping the dns server."}`)


    var answ Answer

    if err := json.Unmarshal(errProxy, &answ); err != nil {

        log.Fatal(err)

    }

    fmt.Println(answ)


    answ = Answer{}

    if err := json.Unmarshal(errServer, &answ); err != nil {

        log.Fatal(err)

    }

    fmt.Println(answ)

}


去游乐场


上面示例中的关键是包含两种变体的类型。我们还可以简化这一点,因为这两个错误都可以包含在ErrorResponse类型中:


type Answer struct {

    Errors ErrorResponse `json:"errors"`

}


type ErrorResponse struct {

    ID      string

    Message string

    Status  string

}


func (s *ErrorResponse) UnmarshalJSON(b []byte) error {

    if len(b) == 0 {

        // no data, nothing to do

        return nil

    }

    if b[0] == '{' {

        // is object

        var tmp struct {

            ID      string `json:"id"`

            Message string `json:"message"`

            Status  string `json:"status"`

        }

        if err := json.Unmarshal(b, &tmp); err != nil {

            return err

        }

        s.ID = tmp.ID

        s.Message = tmp.Message

        s.Status = tmp.Status

        return nil

    }

    return json.Unmarshal(b, &s.Message)

}

Error这里不需要该结构。


查看完整回答
反对 回复 2022-06-27
  • 3 回答
  • 0 关注
  • 121 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号