To Json:

type Address struct {
	Province string
	City     string
	Phone    string
}

func (a *Address) MarshalJSON() ([]byte, error) {
	return []byte(`"` + a.Province + " " + a.City + `"`), nil
}

type User struct {
	Name     string                          // Default will be Name
	Username string `json:"username"`        // Custom json key
	Password string `json:“-”`               // Don't include in json
	Image    string `json:"image,omitempty"` // Don't include in json if empty
	Address  Address                         // Custom type with custom json
}

// Fully custom MarshalJSON()
func (u *User) MarshalJSON() ([]byte, error) {
	type wrapper User
	return json.Marshal(&struct {
		*wrapper
		Phone string `json:"phone"`
	}{
		wrapper: (*wrapper)(u),
		Phone:   u.Address.Phone,
	})
}

//func (u User) MarshalJSON() ([]byte, error) {
//
//}
func main() {
	// with empty image
	user1 := User{
		Name:     "User",
		Username: "Username",
		Password: "Password",
		Image:    "",
		Address: Address{
			Province: "Province",
			City:     "City",
			Phone:    "aaaaa",
		},
	}
	// with image
	user2 := User{
		Name:     "User",
		Username: "Username",
		Password: "Password",
		Image:    "image.png",
		Address: Address{
			Province: "Province",
			City:     "City",
			Phone:    "aaaaa",
		},
	}
	//Notice: The difference between Pointer and Value function
	json1, _ := json.Marshal(user1)
	json2, _ := json.Marshal(&user1)
	json3, _ := json.Marshal(user2)
	json4, _ := json.Marshal(&user2)

	// No phone field
	fmt.Println(string(json1))
	// Out: {"Name":"User","username":"Username","Password":"Password","Address":{"Province":"Province","City":"City","Phone":"aaaaa"}}

	// With phone field
	fmt.Println(string(json2))
	// Out: {"Name":"User","username":"Username","Password":"Password","Address":"Province City","phone":"aaaaa"}

	fmt.Println(string(json3))
	// Out: {"Name":"User", "username":"Username", "Password":"Password", "image":"image.png", "Address":{"Province":"Province", "City":"City", "Phone":"aaaaa"}}
	fmt.Println(string(json4))
	// Out: {"Name":"User", "username":"Username", "Password":"Password", "image":"image.png", "Address":"Province City","phone":"aaaaa"}

	// Write directly to io
	encoder := json.NewEncoder(os.Stdout)
	encoder.Encode(user1)
	encoder.Encode(&user1)
	encoder.Encode(user2)
	encoder.Encode(&user2)
}

From Json:


type Address struct {
	Province string
	City     string
	Phone    string
}

type User struct {
	Name     string                          // Default will be Name
	Username string `json:"username"`        // Custom json key
	Password string `json:“-”`               // Useless on unmarshal
	Image    string `json:"image,omitempty"` // Useless on unmarshal
	Address  Address                         // Custom type with custom json
}

func main() {

	json1 := []byte(`{"Name":"User","username":"Username","Password":"Password","image":"image.png","Address":"Province City","phone":"aaaaa"}`)
	json2 := []byte(`[{"Name":"User","username":"Username","Password":"Password","image":"image.png","Address":"Province City","phone":"aaaaa"},{"Name":"User","username":"Username","Password":"Password","image":"image.png","Address":"Province City","phone":"aaaaa"}]`)

	json3 := []byte(`{"Name":"User","username":"Username","Password":"Password1","Image":"Ima.png","Address":{"Province":"Province","City":"City","Phone":"aaaaa"}}`)

	// map[string]interface{} & []map[string]interface{}
	var result1 map[string]interface{}
	var result2 []map[string]interface{}

	json.Unmarshal(json1, &result1)
	json.Unmarshal(json2, &result2)

	// dealing with json in json
	// {"address":{"province":"Province"}}
	// result["address"].(map[string]interface{})

	// dealing with array
	// {"addresses":[{{"province":"Province", code:200}},{"province":"Province", code:200}]}
	// result["address"].([]map[string]interfacee{})

	// struct

	// Notice: Username field, the username and Username are both valid key.
	var user User
	json.Unmarshal(json3, &user)

	// From io.Reader
	decoder := json.NewDecoder(bytes.NewReader(json3))
	decoder.Decode(&user)

}

// fully custom
func (u *User) UnmarshalJSON(jsonBytes []byte) error {
	var result map[string]interface{}
	json.Unmarshal(jsonBytes, &result)
	// then you can do everything you want
	//
	// custom type
	// u.Address = Address{
	//   Province:result["Province"].(string),
	// }

	// enum type
	// if result["type"].(string) != "ValidA" { return errors.New("Invalid type") }
	//
	// custom datetime
	// time.Parse(format, result["time"].(string))

	return nil
}