dongyi7901 2018-06-28 02:05
浏览 34

有条件地解组JSON的干净方法

I'm sending requests to a JSON API, and it either returns an error...

{
  "error": {
    "code": 404,
    "message": "Document not found.",
    "status": "NOT_FOUND"
  }
}

or the data.

{
  "name": "projectname",
  "fields": {
    "userId": {
      "stringValue": "erw9384rjidfge"
    }
  },
  "createTime": "2018-06-28T00:52:25.638791Z",
  "updateTime": "2018-06-28T00:52:25.638791Z"
}

Here are the corresponding structs

type HttpError struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Status  string `json:"status"`
}

type Document struct {
    Name   string `json:"name"`
    Fields struct {
        UserID struct {
            StringValue string `json:"stringValue"`
        } `json:"userId"`
    } `json:"fields"`
    CreateTime time.Time `json:"createTime"`
    UpdateTime time.Time `json:"updateTime"`
}

Once I get the response, how do I cleanly/concisely unmarshal to the correct struct? I've seen a lot of ugly solutions (maybe Go's fault instead of the writers).

func getDocument() {
    resp, _ := httpClient.Get("example.com")
    defer resp.Body.Close()
    bodyBytes, _ := ioutil.ReadAll(resp.Body)

    var data map[string]interface{}
    // How to unmarshal to either HttpError or Document??
    err = json.Unmarshal([]byte(bodyBytes), &data)

}

By the way, I can't use the Go Firestore client library because reasons.

  • 写回答

1条回答 默认 最新

  • dongpu9852 2018-06-28 09:02
    关注

    You can use an struct type inside your unmarshal method; with pointers to establish what's been unmarshalled.

    Note: This code assumes there is no overlap of top level json keys... error / name / fields / etc.

    type outer struct {
        *HttpError `json:"error"`
        *Document
    }
    
    var out outer
    
    if err := json.Unmarshal(bodyBytes, &out); err != nil {
        // error handling
    }
    
    if out.HttpErr != nil {
        // handle error json case
    }
    
    // Here you can use out.Document, probably worth check if it is nil first.
    

    Runnable example

    评论

报告相同问题?

悬赏问题

  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥30 BC260Y用MQTT向阿里云发布主题消息一直错误
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)