dongxuxian6930 2019-01-03 16:10
浏览 63
已采纳

如何解析包装的json对象

some API endpoint may return successful result or error like this:

// ok
{
    "status": "ok",
    "payload": {
        "id": 10,
        "title": "Sample"
    },
    "request_id": "lx-VHr4OLm"
}
// error
{
    "status": "error",
    "payload": {
        "message": "internal error"
    },
    "trace_id": "lx-VHr4OLm"
}

I'm trying to find elegant way to parse with Go, something like this

.... some code
if status == "ok" {
    struct := AppStruct{} // AppStruct contains 2 fields: id and title
    _ := json.Unmarshall(payloadBody, &struct)
    return struct 
} else {
    errorStruct := ErrorStruct{} // contains 1 field for message.
    _ := json.Unmarshall(payloadBody, &errorStruct) 
    return nil, errors.New(errorStruct.Message)
}

My current code not works for success payload:

var result map[string]interface{}
jsonErr := json.Unmarshal(body, &result)
if jsonErr != nil {
    return nil, jsonErr
}
if result["status"] == "error" {
    errorPayload := result["payload"].(map[string]string)
    return nil, errors.New(errorPayload["message"])
} else if result["status"] == "ok" {
    apiResponse := AppInfo{}
    jsonErr := json.Unmarshal([]byte(result["payload"].(string)), &apiResponse)
    if jsonErr != nil {
        return nil, jsonErr
    }
    return &apiResponse, nil
}

And I got runtime error on line json.Unmarshal([]byte(result["payload"].(string)), &apiResponse)

http: panic serving [::1]:51091: interface conversion: interface {} is map[string]interface {}, not string

Surely, I may have 2 structs: for success response and for error one but I assume it's too complicated way to solve my problem.

How to parse this JSON in elegant way?

  • 写回答

2条回答 默认 最新

  • duanqian6982 2019-01-03 17:09
    关注

    Thanks https://stackoverflow.com/users/965900/mkopriva for idea to use json.RawMessage

    My final solution:

    func parsePayload(response []byte, successPayload interface{}) error {
        var result map[string]json.RawMessage
        jsonErr := json.Unmarshal(response, &result)
        if jsonErr != nil {
            return jsonErr
        }
        var status string
        jsonErr = json.Unmarshal(result["status"], &status)
        if jsonErr != nil {
            return jsonErr
        }
        if status == "ok" {
            jsonErr = json.Unmarshal(result["payload"], &successPayload)
            if jsonErr != nil {
                return jsonErr
            }
            return nil
        } else if status == "error" {
            errorPayload := ErrorPayload{}
            jsonErr = json.Unmarshal(result["payload"], &errorPayload)
            if jsonErr != nil {
                return jsonErr
            }
            return errors.New(errorPayload.Message)
        }
        log.Printf("Unknown http result status: %s", status)
        return errors.New("internal error")
    }
    
    type ErrorPayload struct {
        Message string `json:"message"`
    }
    
    //usage
    
    type AppInfo struct {
        Id    int    `json:"app_id"`
        Title string `json:"app_title"`
    }
    
    body := ... // read body
    appInfo := AppInfo{}
    parseErr := parsePayload(body, &appInfo)
    if parseErr != nil {
        return nil, parseErr
    }
    log.Printf("Parsed app %v", appInfo)
    return &appInfo, nil
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法