This question already has an answer here:
I experience problem with marshalling and unmarshalling nested structure. Code bellow:
type MembersOrlearners struct {
membs []*membership.Member `json:"members"`
learns []*membership.Learner `json:"learners"`
}
func (h *peerMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !allowMethod(w, r, "GET") {
return
}
w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
if r.URL.Path != peerMembersPrefix {
http.Error(w, "bad path", http.StatusBadRequest)
return
}
ms := h.cluster.Members()
ls := h.cluster.Learners()
var lm MembersOrlearners
lm.membs = ms
lm.learns = ls
w.Header().Set("Content-Type", "application/json")
hh := json.NewEncoder(w)
if err := hh.Encode(lm); err != nil {
plog.Warningf("failed to encode members response (%v)", err)
}
}
I try to unmarshal it , but I get this error: could not unmarshal cluster response: invalid character 'b' looking for beginning of value
func getClusterFromRemotePeers(urls []string, timeout time.Duration, logerr bool, rt http.RoundTripper) (*membership.RaftCluster, error) {
cc := &http.Client{
Transport: rt,
Timeout: timeout,
}
type membersOrlearners struct {
membs []*membership.Member `json:"members"`
learns []*membership.Learner `json:"learners"`
}
var ml membersOrlearners
for _, u := range urls {
resp, err := cc.Get(u + "/members")
if err != nil {
if logerr {
plog.Warningf("could not get cluster response from %s: %v", u, err)
}
continue
}
b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
if logerr {
plog.Warningf("could not read the body of cluster response: %v", err)
}
continue
}
if err = json.Unmarshal(b, &ml); err != nil {
if logerr {
plog.Warningf("could not unmarshal cluster response: %v", err)
}
continue
}
id, err := types.IDFromString(resp.Header.Get("X-Etcd-Cluster-ID"))
if err != nil {
if logerr {
plog.Warningf("could not parse the cluster ID from cluster res: %v", err)
}
continue
}
// check the length of membership members
// if the membership members are present then prepare and return raft cluster
// if membership members are not present then the raft cluster formed will be
// an invalid empty cluster hence return failed to get raft cluster member(s) from the given urls error
if len(ml.membs) > 0 {
return membership.NewClusterFromMembers("", id,ml.membs,ml.learns), nil
}
return nil, fmt.Errorf("failed to get raft cluster member(s) from the given urls.")
}
return nil, fmt.Errorf("could not retrieve cluster information from the given urls")
}
Could you please explain me what am I doing wrong? Is it a marshal or unmarshal matter?
I tried to marshal and unmarshal once only for membs and once only for learns (without struct membersOrlearners usage, just using a var membs and learns accordingly) and it works fine.
I need to use them both.
</div>