Serialization 具有io.Reader的Golang结构无法序列化
我试图将下面的struct序列化为Serialization 具有io.Reader的Golang结构无法序列化,serialization,go,deserialization,Serialization,Go,Deserialization,我试图将下面的struct序列化为byte[]以将其存储到DB中,然后在从DB中读取它的同时,对其进行反序列化 type Response struct { Headers map[string][]string Body io.Reader Status int } 下面是我如何创建响应对象并为其设置值的代码 resp := new(Response) resp.Body = bytes.NewReader(outBytes) //outBytes is by
byte[]
以将其存储到DB中,然后在从DB中读取它的同时,对其进行反序列化
type Response struct {
Headers map[string][]string
Body io.Reader
Status int
}
下面是我如何创建响应对象并为其设置值的代码
resp := new(Response)
resp.Body = bytes.NewReader(outBytes) //outBytes is byte[]
resp.Headers.SetKeyValue("Content-Type", "text/json") //SetKeyValue is the method created for adding headers
resp.Headers.SetKeyValue("Url-Type", "broker")
resp.Status = 200
我正在使用json.Marshal()
序列化resp
对象,如下所示
b, _ := json.Marshal(resp)
下面是我用来反序列化的代码
var r Response
r.Body = &bytes.Buffer{}
json.Unmarshal(b,&r)
问题在于反序列化,我无法获取resp.Body
对象。尽管设置了body object(参见上文),但它始终为nil
或空白。我可以从反序列化中获取结构的标题
和状态
字段,但不能从正文
中获取
我知道有一些东西需要处理Body
字段,它是一个io.Reader
任何帮助都会非常好。我正在使用“encoding/json”
包:
因为我可以使用http.ResponseWriter发送JSON响应。以下两个函数可用于发送JSON和从正文中读取JSON:
// GetJSONContent returns the JSON content of a request
func GetJSONContent(v interface{}, r *http.Request) error {
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(v)
}
// JSONWithHTTPCode Json Output with an HTTP code
func JSONWithHTTPCode(w http.ResponseWriter, d interface{}, code int) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(code)
if d != nil {
err := json.NewEncoder(w).Encode(d)
if err != nil {
panic(err)
}
}
}
然后在处理程序中,只需按如下方式使用这些func:
// Handler handler
func Handler(w http.ResponseWriter, r *http.Request) {
s := YourStruct{}
err = GetJSONContent(s, r)
if err != nil {
panic(err)
}
return
}
JSONWithHTTPCode(w, s, http.StatusOK)
}
希望它有帮助我正在使用编码/json”
包:
因为我可以使用http.ResponseWriter发送JSON响应。以下两个函数可用于发送JSON和从正文中读取JSON:
// GetJSONContent returns the JSON content of a request
func GetJSONContent(v interface{}, r *http.Request) error {
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(v)
}
// JSONWithHTTPCode Json Output with an HTTP code
func JSONWithHTTPCode(w http.ResponseWriter, d interface{}, code int) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(code)
if d != nil {
err := json.NewEncoder(w).Encode(d)
if err != nil {
panic(err)
}
}
}
然后在处理程序中,只需按如下方式使用这些func:
// Handler handler
func Handler(w http.ResponseWriter, r *http.Request) {
s := YourStruct{}
err = GetJSONContent(s, r)
if err != nil {
panic(err)
}
return
}
JSONWithHTTPCode(w, s, http.StatusOK)
}
希望对您有所帮助。简短回答:JSON marshaller不会使用
Read()
函数从io.Reader读取字符串。您可以使用实现封送处理程序
接口的类型,而不是使用io.Reader
马歇尔勒的工作原理:
封送处理递归地遍历值v。如果遇到的值实现了Marshaler
接口,并且不是nil指针,则Marshal将调用其MarshalJSON
方法来生成JSON。如果不存在MarshalJSON方法,但该值实现了encoding.textmasharler
,则Marshal将调用其MarshalText
方法。nil指针异常并不是严格必需的,但它模拟了解组JSON行为中类似的必需异常
否则,封送处理将使用以下依赖于类型的默认编码:
- 布尔值编码为JSON布尔值李>
- 浮点、整型和数值编码为JSON数字
type Response struct {
Headers map[string][]string
Body *JSONReader
Status int
}
type JSONReader struct {
*bytes.Reader
}
func NewJSONReader(outBytes []byte) *JSONReader {
jr := new(JSONReader)
jr.Reader = bytes.NewReader(outBytes)
return jr
}
func (js JSONReader) MarshalJSON() ([]byte, error) {
data, err := ioutil.ReadAll(js.Reader)
if err != nil {
return nil, err
}
data = []byte(`"` + string(data) + `"`)
return data, nil
}
// UnmarshalJSON sets *jr to a copy of data.
func (jr *JSONReader) UnmarshalJSON(data []byte) error {
if jr == nil {
return errors.New("json.JSONReader: UnmarshalJSON on nil pointer")
}
if data == nil {
return nil
}
data = []byte(strings.Trim(string(data), "\""))
jr.Reader = bytes.NewReader(data)
return nil
}
下面是一个关于实现和示例用法的go Playerly链接:简短回答:JSON marshaller不会使用
Read()
函数从io.Reader读取字符串。您可以使用实现封送处理程序
接口的类型,而不是使用io.Reader
马歇尔勒的工作原理:
封送处理递归地遍历值v。如果遇到的值实现了Marshaler
接口,并且不是nil指针,则Marshal将调用其MarshalJSON
方法来生成JSON。如果不存在MarshalJSON方法,但该值实现了encoding.textmasharler
,则Marshal将调用其MarshalText
方法。nil指针异常并不是严格必需的,但它模拟了解组JSON行为中类似的必需异常
否则,封送处理将使用以下依赖于类型的默认编码:
- 布尔值编码为JSON布尔值李>
- 浮点、整型和数值编码为JSON数字
type Response struct {
Headers map[string][]string
Body *JSONReader
Status int
}
type JSONReader struct {
*bytes.Reader
}
func NewJSONReader(outBytes []byte) *JSONReader {
jr := new(JSONReader)
jr.Reader = bytes.NewReader(outBytes)
return jr
}
func (js JSONReader) MarshalJSON() ([]byte, error) {
data, err := ioutil.ReadAll(js.Reader)
if err != nil {
return nil, err
}
data = []byte(`"` + string(data) + `"`)
return data, nil
}
// UnmarshalJSON sets *jr to a copy of data.
func (jr *JSONReader) UnmarshalJSON(data []byte) error {
if jr == nil {
return errors.New("json.JSONReader: UnmarshalJSON on nil pointer")
}
if data == nil {
return nil
}
data = []byte(strings.Trim(string(data), "\""))
jr.Reader = bytes.NewReader(data)
return nil
}
下面是一个go Playerd链接,其中包含实现和示例用法:概述
是一个接口,因此无法封送。每个封送结构属性都必须实现要封送的接口。您可以声明自己的封送处理程序包装结构来封送来自字节的数据。Reader
为什么接口不能被封送?
Go中的接口提供了一种指定对象行为的方法:如果有什么东西可以做到这一点,那么可以在这里使用它。相反,Go的结构是字段的类型化集合。它们对于将数据分组形成记录很有用。Go支持在结构类型而不是接口类型上定义的方法
实施
概述
是一个接口,因此无法封送。每个封送结构属性都必须实现要封送的接口。您可以声明自己的封送处理程序包装结构来封送来自字节的数据。Reader
为什么接口不能被封送?
Go中的接口提供了一种指定对象行为的方法:如果有什么东西可以做到这一点,那么可以在这里使用它。相反,Go的结构是字段的类型化集合。它们对于将数据分组形成记录很有用。Go支持在结构类型而不是接口类型上定义的方法
实施
您使用了错误的结构,
io。Reader
仅为and接口和字节。Reader
没有任何导出属性,因此Body
为空。您应该将Body
的类型更改为对您有帮助的类型,如string
,或者您可以只使用[]byte
谢谢,我已将Body字段定义为可以从任何流读取数据的流,我无法更改字段类型。我不明白为什么有人提出我的问题。如果Headers
是一个映射,那么它上怎么会有函数“SetKeyValue”?我定义了一个类型Headers映射[HeaderKey][]字符串,Headers是Headers类型,那么该方法就是这种类型。为了让我的问题小一些,我把它的简短版本放在这里。您可以认为该方法只是添加标题的方法。您使用了错误的结构,io。Reader
只是and接口和字节。Reader
没有任何导出属性,因此Body
是blan