Value object to json in go

Viewed 592

I have a struct which contains an other struct as value object.

type User struct {
    Name  string            `json:"name"``
    Email valueobject.Email `json:"email"`
}

The valueobject.Email looks like this:

type Email struct {
    value string
}
func (e *Email) Value() string {
    return e.Value
}

I want the value object as an immutable object, there is also a "factory" method in this is not necessary for my problem.

Now I want to return the User struct as json and therefor I use

response := map[string]interface{}{"user": User}
json.NewEncoder(w).Encode(response)

The result is:

{
    "user": {
        "name": "John Doe",
        "email": {
            "Email: "johndoe@example.com"
        }
    }
}

But I want something link this:

{
    "user": {
        "name": "John Doe",
        "email": "johndoe@example.com"
    }
}
2 Answers

It sounds like you need valueobject.Email to implement the json.Marshaler interface:

func (e *Email) MarshalJSON() ([]byte, error) {
  return json.Marshal(e.Value())
}

That is the bare-minimum to implement what you are asking for. By implementing the json.Marshaler interface, it allows you to customize how json.Marshal renders your value.

Another option is to simplify Email into just a wrapper for string, instead of a struct:

type Email string

func (e Email) Value() string {
  return e
}

Since strings are already handled by json.Marshal, it should just work.

To make your Email type marshal the way you'd like, you'll need to make it implement the json.marshaler interface. GopherAcademy uses the following example:

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