如何解组不同的json格式

我读了很多类似的问题,但还没有找到正确的解决方案。希望有人能给我更好的主意。


我的错误响应可能是以下格式之一:


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

}


宝慕林4294392
浏览 144回答 3
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)    }}

森林海

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

慕盖茨4494581

有趣的是,我只是在这里给出了这个问题的答案:使用自定义UnmarshalJSON函数。你如何在 Golang 中修改这个结构来接受两个不同的结果?适用于您的情况:package mainimport (    "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这里不需要该结构。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go