英文:
Parse http json request based on a field in json
问题
我想使用encoding/json
中的Decode()
函数解码一个传入的POST请求的JSON负载。
然而,我遇到了一个情况,即相同的HTTP请求的JSON主体可能不同。我想根据JSON中嵌入的字段来区分这个主体。在Go语言中,如何提取这个单一字段呢?例如,我想要以下逻辑:
type BaseObj struct {
Version string
}
type v1Object struct {
BaseObj
Name string
}
type v2Object struct {
BaseObj
Name string
Address string
}
// 从JSON(req.Body)中提取'version'
if version == "v1" {
var data v1Object
json.NewDecoder(req.Body).Decode(&data)
} else {
var data v2Object
json.NewDecoder(req.Body).Decode(&data)
}
如何获取主体中的'version'字段呢?
谢谢你的帮助!
英文:
I want to decode an incoming JSON payload of a POST request using the Decode()
function from encoding/json
However, I have a case where the body of the JSON can be different for the same http request. I want to differentiate this body based on a field embedded in the JSON. How can I extract this singular field in Go? For instance, I want the following logic-
type BaseObj struct {
Version string
}
type v1Object struct {
BaseObj
Name string
}
type v2Object struct {
BaseObj
Name string
Address string
}
// Somehow extract the 'version' from JSON (req.Body)
if version == "v1" {
var data v1Object
json.NewDecoder(req.Body).Decode(&data)
} else {
var data v2Object
json.NewDecoder(req.Body).Decode(&data)
}
How can I get the 'version' field embedded in the body?
Thanks for your help!
答案1
得分: 1
有两种方法可以解决这个问题:
解决方案1:使用核心库的方式
只使用核心库,你可以这样做:
import (
"bytes"
"ioutil"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 首先读取请求体内容以便重用
type protoData struct {
Version string `json:"version"`
}
proto := protoData{}
content, err := ioutil.ReadAll(req.Body)
json.NewDecoder(bytes.NewBuffer(content)).Decode(&proto)
// 版本切换
if proto.Version == "v1" {
var data v1Object
json.NewDecoder(bytes.NewBuffer(content)).Decode(&data)
// ... 使用 data 做一些操作
} else {
var data v2Object
json.NewDecoder(bytes.NewBuffer(content)).Decode(&data)
// ... 使用 data 做一些操作
}
}
解决方案2:使用 lzjson 库的方式
我写了一个简单的库,lzjson,可以使代码更清晰。
import (
"net/http"
"github/go-restit/lzjson"
)
func handler(w http.ResponseWriter, r *http.Request) {
jsonBody := lzjson.Decode(r.Body)
version := jsonBody.Get("version").String()
if version == "v1" {
var data v1Object
jsonBody.Unmarshal(&data)
// ... 使用 data 做一些操作
} else {
var data v2Object
jsonBody.Unmarshal(&data)
// ... 使用 data 做一些操作
}
}
英文:
There are 2 ways to solve this issue:
Solution 1: Core Library Way
By only using the core library, you may do this:
<!--language:golang-->
import (
"bytes"
"ioutil"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
// read body content first to reuse
type protoData struct {
Version string `json:"version"`
}
proto := protoData{}
content, err := ioutil.ReadAll(req.Body)
json.NewDecoder(bytes.NewBuffer(content)).Decode(&proto)
// version switch
if proto.Version == "v1" {
var data v1Object
json.NewDecoder(bytes.NewBuffer(content)).Decode(&data)
// ... do something with data
} else {
var data v2Object
json.NewDecoder(bytes.NewBuffer(content)).Decode(&data)
// ... do something with data
}
}
Solution 2: lzjson Way
I've written a silly library, lzjson, to make the code cleaner.
<!--language:golang-->
import (
"net/http"
"github/go-restit/lzjson"
)
func handler(w http.ResponseWriter, r *http.Request) {
jsonBody := lzjson.Decode(r.Body)
version := jsonBody.Get("version").String()
if version == "v1" {
var data v1Object
jsonBody.Unmarshal(&data)
// ... do something with data
} else {
var data v2Object
jsonBody.Unmarshal(&data)
// ... do something with data
}
}
答案2
得分: 0
以下是翻译好的内容:
type BaseObj struct {
Version string
}
type v1Object struct {
BaseObj
Name string
}
type v2Object struct {
BaseObj
Name string
Address string
}
var response map[string]string
json.Unmarshal(req.Body, &response)
if response["version"] == "v1" {
var data v1Object
json.NewDecoder(req.Body).Decode(&data)
} else {
var data v2Object
json.NewDecoder(req.Body).Decode(&data)
}
total solution is not good but this is the way you could use data
这是你可以使用数据的方式,整体解决方案可能不太好。
英文:
type BaseObj struct {
Version string
}
type v1Object struct {
BaseObj
Name string
}
type v2Object struct {
BaseObj
Name string
Address string
}
var response map[string]string
json.Unmarshal(req.Body, &response)
if response["version"] == "v1" {
var data v1Object
json.NewDecoder(req.Body).Decode(&data)
} else {
var data v2Object
json.NewDecoder(req.Body).Decode(&data)
total solution is not good but this is the way you could use data
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论