基于 JSON 中的字段解析 HTTP JSON 请求。

huangapple go评论85阅读模式
英文:

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 (
    &quot;bytes&quot;
    &quot;ioutil&quot;
    &quot;net/http&quot;
)

func handler(w http.ResponseWriter, r *http.Request) {

    // read body content first to reuse
    type protoData struct {
        Version string `json:&quot;version&quot;`
    }
    proto := protoData{}
    content, err := ioutil.ReadAll(req.Body)
    json.NewDecoder(bytes.NewBuffer(content)).Decode(&amp;proto)

    // version switch
    if proto.Version == &quot;v1&quot; {
            var data v1Object
            json.NewDecoder(bytes.NewBuffer(content)).Decode(&amp;data)
            // ... do something with data
    } else {
            var data v2Object
            json.NewDecoder(bytes.NewBuffer(content)).Decode(&amp;data)
            // ... do something with data
    }

}

Solution 2: lzjson Way

I've written a silly library, lzjson, to make the code cleaner.

<!--language:golang-->

import (
    &quot;net/http&quot;

    &quot;github/go-restit/lzjson&quot;
)

func handler(w http.ResponseWriter, r *http.Request) {
    jsonBody := lzjson.Decode(r.Body)
    version := jsonBody.Get(&quot;version&quot;).String()
    if version == &quot;v1&quot; {
        var data v1Object
        jsonBody.Unmarshal(&amp;data)
        // ... do something with data
    } else {
        var data v2Object
        jsonBody.Unmarshal(&amp;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, &amp;response)

if response[&quot;version&quot;] == &quot;v1&quot; {
        var data v1Object
        json.NewDecoder(req.Body).Decode(&amp;data)
} else {
        var data v2Object
        json.NewDecoder(req.Body).Decode(&amp;data)

total solution is not good but this is the way you could use data

huangapple
  • 本文由 发表于 2017年2月11日 11:13:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/42171765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定