package main

import (
	"encoding/json"
	"fmt"
	"log"
)

type Animal interface {
	json.Marshaler
	json.Unmarshaler
	Color() string
}

type Dog struct {
	Name       string
	ColorOfFur string
}

func (d *Dog) ComposeName(title, firstName, lastName string) {
	d.Name = title + " " + firstName + " " + lastName
}

func (d *Dog) Color() string {
	return d.ColorOfFur
}

func (d *Dog) MarshalJSON() ([]byte, error) {
	return json.Marshal(*d)
}

func (d *Dog) UnmarshalJSON(buf []byte) error {
	type DogAlias Dog
	var tmpDog DogAlias
	err := json.Unmarshal(buf, &tmpDog)
	if err != nil {
		// leave d untouched
		return err
	}
	*d = Dog(tmpDog)
	return nil
}

func main() {
	doggo := Dog{"Cooper", "Purple"}
	var someAnimal Animal
	someAnimal = &doggo

	buf, err := json.Marshal(someAnimal)

	if err != nil {
		log.Fatal("Error marshaling:", err)
	}

	fmt.Println("Our Animal:", string(buf))

	var jsonDog Dog
	err = json.Unmarshal(buf, &jsonDog)

	if err != nil {
		log.Fatal("Error unmarshaling:", err)
	}

	fmt.Println("Our new jsonDog:", jsonDog)
}
