英文:
Invalid null added to HTTP response JSON body when reading with ioutil in golang
问题
这个问题让我头疼不已。我甚至不确定标题是否完全正确,因为我很难将问题缩小到一个具体的部分。
我有两个应用程序通过REST相互通信。其中一个应用程序接受来自另一个应用程序的HTTP GET请求,并返回一些JSON数据。对于HTTP路由器,我使用的是Gorilla/mux。到目前为止还好。
我的第一个应用程序(我们称之为FooReader
)通过HTTP GET调用我的第二个应用程序(我们称之为FooWriter
):
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("uuid", "my uuid")
req.Header.Set("api_token", "my token")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
...
}
defer resp.Body.Close()
这个工作得很好。你可以看到我在头部发送了一些额外的内容,这就是为什么我没有使用http.Get()
。(有更好的方法吗?)
现在FooWriter
接收到该请求并进行处理:
...
var successJSON = "{\"foo\":\"bar\"}"
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write([]byte(successJSON))
w.WriteHeader(200)
if err := json.NewEncoder(w).Encode(err); err != nil {
...
}
回到FooReader
,我现在接收来自FooWriter
的响应并读取它(为了清晰起见,我再次添加了Do()调用):
resp, err := client.Do(req)
if err != nil {
...
}
defer resp.Body.Close()
fmt.Println("response Code:", resp.StatusCode)
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
if err != nil {
...
}
fmt.Println("response Body:", string(body))
现在出现了奇怪的情况:当我像最后一行那样打印响应正文时,原始的JSON字符串中会添加一个额外的null
:
response Code: 200
response Body: {"foo":"bar"}null
我猜测在JSON解码之前有一些nil
被添加进去了,但我就是找不到它。
另外,我猜测问题可能出在FooReader
这一侧,因为我在应用程序的其他部分上在FooWriter
这一侧使用了完全相同的代码,而那部分代码运行良好。
我有什么遗漏吗?非常感谢任何帮助!
英文:
So this one is driving me insane. I'm not even sure if the title is 100% correct because I'm having some trouble to narrow the issue down to one specific part.
I have two applications that talk to each other via REST. One accepts the HTTP GET request from the other app, and answers with some JSON. For the HTTP router I use Gorilla/mux btw. So far so good.
My first application (let's call it FooReader
), is calling my second application (let's call it FooWriter
) via HTTP GET:
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("uuid", "my uuid")
req.Header.Set("api_token", "my token")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
...
}
defer resp.Body.Close()
This works just fine. As you can see I'm sending some additional stuff in the header, that's why I'm not using http.Get()
. (Is there a better way to do this?)
Now FooWriter
receives that request and processes it:
...
var successJSON = "{\"foo\":\"bar\"}"
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write([]byte(successJSON))
w.WriteHeader(200)
if err := json.NewEncoder(w).Encode(err); err != nil {
...
}
Back in FooReader
I now receive the response from FooWriter
and read it (I've added the Do() call again for clarity):
resp, err := client.Do(req)
if err != nil {
...
}
defer resp.Body.Close()
fmt.Println("response Code:", resp.StatusCode)
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1048576))
if err != nil {
...
}
fmt.Println("response Body:", string(body))
Now comes the weird part: When I print the response body like I do in the last line, there is an additional null
added to the original JSON string:
response Code: 200
response Body: {"foo":"bar"}null
My guess is that there is some nil
thrown in there before the JSON decoding, but I just can't find it.
Also I'm guessing that the issue has to be on the FooReader
side, because I'm using the exact same code on FooWriter
side on some other part of the application, which works fine.
Did I miss anything? Any help is much appreciated!
答案1
得分: 1
if err := json.NewEncoder(w).Encode(err)
当 err 为 nil 时打印 null。将 response 传递给 encode 并将 err 作为其一部分,这样只会打印一个 JSON 结构。
英文:
if err := json.NewEncoder(w).Encode(err)
is printing null when err is nil. Pass response to encode and make err part of it so only one json structure is printed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论