Encoding/json bug

package main

import (
	"encoding/json"
	"fmt"
)

type RawJson struct {
	RawMessage []byte
}

func (r *RawJson) MarshalJSON() ([]byte, error) {
	fmt.Println("Marshal Raw")
	return r.RawMessage, nil
}

func (r *RawJson) UnmarshalJSON(d []byte) error {
	fmt.Println("Unmarshal Raw")
	r.RawMessage = d
	return nil
}

type Test1 struct {
	Sdsdsdsd string `json:"sdsdsdsd"`
	Name     string `json:"name"`
}

func (r *Test1) MarshalJSON() ([]byte, error) {
	fmt.Println("Marshal Test1")
	type Alias Test1
	aux := (*Alias)(r)
	return json.Marshal(&aux)
}

func (r *Test1) UnmarshalJSON(d []byte) error {
	fmt.Println("Unmarshal Test1")
	type Alias Test1
	aux := (*Alias)(r)
	return json.Unmarshal(d, aux)
}

type Test struct {
	Test1
	RawJson RawJson `json:"embeded"`
}

var testJson = `{

	"name":"testtest",
	"embeded":{
		"test":1,
		"xxx":1,
		"yyy":[1,2,4,5]
	},
    "sdsdsdsd" : "sdsd"

}`

func main() {

	t := &Test{}
	json.Unmarshal([]byte(testJson), &t)
	fmt.Printf("%v \n", t.Sdsdsdsd)

	b, _ := json.Marshal(t)
	fmt.Println(string(b))
}

If you have custom unmarshel for both types Test1 and RawJson - only one will be cold (unmarsheler for Test1 ) , but when we delete custom unmarsheler for Test1 Raw custom unmarsheler starts working

By embedding Test1 in Test, Test1.UnmashalJSON is promoted to be Test.UnmarshalJSON. Because of this promotion, Test fulfills json.Unmarshaler, which causes json.Unmarshal to assume that Test knows how to unmarshal itself. Thus json.Unmarshal only calls Test.Unmarshal (i.e., Test1.Unmarshal).

1 Like

ok is there any way to fix it? what can i do if i don’t wnat to chage data struct

Implement Test.UnmarshalJSONand Test.MarshalJSON. This is a bit annoying because the contents of Test1 and Test.RawJson are at the same level in testJson. This can be handled by creating an anonymous struct that has the fields in Test that aren’t in Test1. Here is a working example for unmarshal: https://play.golang.org/p/u6FA4Ktu-A (line 48). Marshal should work in a similar way.

Also, check your errors. Following http://pocketgophers.com/error-checking-while-prototyping/ requires little thinking and lets you see when errors occur. Using log.SetFlags(log.Lshortfile) along with log.Print (instead of fmt.Print) also gives line numbers to help find and give context to debugging output.

It is bad solution becouse i use unmarshel twice on same src data - it means i loose speed minimun twice

It is a good solution because it works.

I don’t know if there is a better solution without changing the data structure.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.