Golang如何从map[string]interface{}类型中提取单个字段值
方案1:使用结构体直接解析(更推荐)
你接收的JSON结构外层嵌套了after字段,只需要补充外层的结构体定义,就可以直接拿到指定字段,不需要处理类型断言,安全性更高:
// 原有Data结构体保留 type Data struct { Id int64 `json:"id"` Amount float64 `json:"amount"` Status string `json:"status"` } // 新增外层请求结构体,匹配你收到的JSON结构 type ReqPayload struct { After Data `json:"after"` Key []int `json:"key"` }
修改changedData函数逻辑如下:
func changedData(w http.ResponseWriter, r *http.Request) { fmt.Println("Coming From API") reqBody, err := ioutil.ReadAll(r.Body) if err != nil { log.Println("读请求体失败:", err) return } fmt.Println("Data coming from API ", string(reqBody)) var payload ReqPayload err = json.Unmarshal(reqBody, &payload) if err != nil { log.Println("JSON解析失败:", err) return } // 直接打印你需要的字段,格式完全匹配需求 fmt.Printf("amount::%.0f\nid:%d\nstatus:%s\n", payload.After.Amount, payload.After.Id, payload.After.Status) }
该方案自动做类型校验和转换,不会出现空指针或者类型不匹配的panic,代码可读性和可维护性更高。
方案2:基于现有map方案修改
如果你不想调整结构体,继续用map[string]interface{}的方式解析,可以手动逐层取字段并做类型断言:
func changedData(w http.ResponseWriter, r *http.Request) { fmt.Println("Coming From API") reqBody, _ := ioutil.ReadAll(r.Body) fmt.Println("Data coming from API ", string(reqBody)) digit := json.NewDecoder(strings.NewReader(string(reqBody))) for digit.More() { var result mark err := digit.Decode(&result) if err != nil { if err != io.EOF { log.Fatal(err) } break } // 先取after字段,断言为map类型 afterMap, ok := result["after"].(map[string]interface{}) if !ok { log.Println("after字段格式错误") continue } // 分别取各个字段,做类型断言 amount, _ := afterMap["amount"].(float64) id, _ := afterMap["id"].(float64) status, _ := afterMap["status"].(string) // 打印目标格式 fmt.Printf("amount::%.0f\nid:%d\nstatus:%s\n", amount, int64(id), status) } }
该方案适合JSON结构不固定的场景,注意需要补充类型断言失败的处理逻辑,避免程序panic。
内容的提问来源于stack exchange,提问作者Mahaprasad Nayak
相关产品推荐
相关产品推荐

