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

时间:2018-06-28 02:05:50

标签: json go google-cloud-firestore

我正在将请求发送到JSON API,它要么返回错误...

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

或数据。

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

这是对应的结构

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"`
}

获得响应后,如何彻底/简明地解组正确的结构?我见过很多丑陋的解决方案(也许是Go的错而不是作家的错)。

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)

}

顺便说一句,由于某些原因,我不能使用Go Firestore客户端库。

1 个答案:

答案 0 :(得分:1)

您可以在unmarshal方法内使用struct类型;带有建立未编组内容的指针。

注意:该代码假定顶级json键没有重叠...错误/名称/字段/等。

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