hjma29
(Hongjun Ma)
June 7, 2017, 4:40pm
1
I’m trying to do json.Marshal directly to http.Response but the returned []byte is nil. I can see the response from http.Get is a valid struct and thought json.Marshall should be able to parse it. Which point am I missing here?
http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Pragma":[]string{"no-cache"}, "Content-Type":[]string{"text/html; charset=utf-8"}, "Connection":[]string{"keep-alive"}, "Expires":[]string{"-1"}, "Server":[]string{"Microsoft-IIS/7.5"}, "X-Powered-By":[]string{"ASP.NET"}, "Cache-Control":[]string{"no-cache"}, "Vary":[]string{"Accept-Encoding"}, "X-Aspnet-Version":[]string{"4.0.30319"}, "Date":[]string{"Wed, 07 Jun 2017 16:35:51 GMT"}, "Age":[]string{"0"}}, Body:(*http.gzipReader)(0xc4201460c0), ContentLength:-1, TransferEncoding:[]string(nil), Close:false, Uncompressed:true, Trailer:http.Header(nil), Request:(*http.Request)(0xc42000a900), TLS:(*tls.ConnectionState)(nil)}
lutzhorn
(Lutz Horn)
June 7, 2017, 5:47pm
2
You forgot to include the code you use. Please also try to make snippets more readable.
1 Like
hjma29
(Hongjun Ma)
June 7, 2017, 6:35pm
3
sorry, here we go.
I’d expect json.Marshall can output the struct fields like {“Struct”: “200 OK”…}
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
resp, _ := http.Get("http://www.httpbin.org")
fmt.Printf("%#v\n", *resp)
respJ, _ := json.Marshal(resp)
fmt.Println("---")
fmt.Println(respJ)
}
the result is
http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"C
ontent-Type":[]string{"text/html; charset=utf-8"}, "Content-Length":[]string{"12793"}, "Access-Control-Allow-Crede
ntials":[]string{"true"}, "X-Powered-By":[]string{"Flask"}, "Connection":[]string{"keep-alive"}, "Server":[]string
{"meinheld/0.6.1"}, "Date":[]string{"Wed, 07 Jun 2017 18:33:42 GMT"}, "Access-Control-Allow-Origin":[]string{"*"},
"X-Processed-Time":[]string{"0.00553107261658"}, "Via":[]string{"1.1 vegur"}}, Body:(*http.bodyEOFSignal)(0xc4200
90380), ContentLength:12793, TransferEncoding:[]string(nil), Close:false, Uncompressed:false, Trailer:http.Header(
nil), Request:(*http.Request)(0xc4200ea300), TLS:(*tls.ConnectionState)(nil)}
---
[]
lutzhorn
(Lutz Horn)
June 7, 2017, 6:43pm
4
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
resp, _ := http.Get("http://www.httpbin.org")
fmt.Printf("%#v\n", *resp)
respJ, err := json.Marshal(resp)
if err != nil {
log.Fatal(err)
}
fmt.Println("---")
fmt.Println(respJ)
}
produces
http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Content-Length":[]string{"12793"}, "Access-Control-Allow-Credentials":[]string{"true"}, "Via":[]string{"1.1 vegur"}, "Connection":[]string{"keep-alive"}, "Date":[]string{"Wed, 07 Jun 2017 18:43:14 GMT"}, "Content-Type":[]string{"text/html; charset=utf-8"}, "Access-Control-Allow-Origin":[]string{"*"}, "X-Powered-By":[]string{"Flask"}, "X-Processed-Time":[]string{"0.00565099716187"}, "Server":[]string{"meinheld/0.6.1"}}, Body:(*http.bodyEOFSignal)(0xc4200e6240), ContentLength:12793, TransferEncoding:[]string(nil), Close:false, Uncompressed:false, Trailer:http.Header(nil), Request:(*http.Request)(0xc42000a800), TLS:(*tls.ConnectionState)(nil)}
2017/06/07 20:43:14 json: unsupported type: func() (io.ReadCloser, error)
exit status 1
That is caused by
Body io.ReadCloser
which above is
Body:(*http.bodyEOFSignal)(0xc4200e6240)
Don’t just ignore err
!
1 Like
hjma29
(Hongjun Ma)
June 7, 2017, 7:47pm
5
Thanks, my bad.
any explanation for this message?
which part of json.Marshal code doesn’t support “func() (io.ReadCloser, error)”? I was trying to trace down the source code but couldn’t figure out myself.
lutzhorn
(Lutz Horn)
June 7, 2017, 7:49pm
6
What do you expect io.ReadCloser
to be serialized to?
I hope we are not trying to solve a XY Problem here. Why are you trying to serialize http.Response
to JSON in the first place?
Have you read this?
https://golang.org/pkg/encoding/json/#Marshal
Based on that it looks like http.Response doesn’t implement a marshaller. Therefore the nil []byte.
https://golang.org/pkg/net/http/#Response
You probably are going to have to create a struct for the JSON output format you desire and marshal that.
type MyJson struct {
Val1 string `json:"val1"`
Val2 int `json:"val2"`
}
1 Like
hjma29
(Hongjun Ma)
June 7, 2017, 10:16pm
8
Thanks. I thought json.Marshal could deal with io.reader hence the confusion.
hjma29
(Hongjun Ma)
June 8, 2017, 12:05am
9
On the same topic, can anyone educate me what’s the meaning and use cases for a struct has interface as its field like the following in golang nett/http package? and how it’s different from emdedding “io.ReadCloser” in Response struct?
type Response struct {
//...
Body io.ReadCloser
//...
}
lutzhorn
(Lutz Horn)
June 8, 2017, 5:05am
10
How would that look like? If you ask for the difference between A and B, please show both A and B, not only A.
hjma29
(Hongjun Ma)
June 8, 2017, 5:32pm
11
thanks. I see bodyEOFSignal struct has a field body with dynamic type http.body struct http.bodyEOFSignal{body:(*http.body)(0xc4200ee200)
and both structs are ReadCloser to work with ioutil.ReadAll. have a better understanding why my original problem was.
func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
es.mu.Lock()
closed, rerr := es.closed, es.rerr
es.mu.Unlock()
if closed {
return 0, errReadOnClosedResBody
}
if rerr != nil {
return 0, rerr
}
n, err = es.body.Read(p)
if err != nil {
es.mu.Lock()
defer es.mu.Unlock()
if es.rerr == nil {
es.rerr = err
}
err = es.condfn(err)
}
return
}
Here’s a brief explanation.
type field struct {
Body io.ReadCloser
}
type embedded struct {
io.ReadCloser
}
As defined here (i.e., without any other code), the main difference between these types is their method sets. field
does not have any methods. embedded
has two methods: Read(p []byte) (n int, err error)
and Close() error
. These methods were promoted from the embedded io.ReadCloser
.
Close
ing the io.ReadCloser
can be done by:
field.Body.Close()
embedded.Close()
(using the promoted method)
embedded.ReadCloser.Close()
(the type name of embedded fields acts as the field name)
The promotion rules are defined in the spec .
1 Like
system
(system)
Closed
September 8, 2017, 5:52am
14
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.