0

Using Go, I'd like to accept a request with json data and translate it to different structs for the outgoing json request.

Here's an example of what I mean:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Greetings struct {
    Greetings []Greeting `json:"data"`
}

type Greeting struct {
    From     string `json:"from"`
    To       string `json:"to"`
    Greeting string `json:"greeting"`
}

type RelationShip struct {
    Messages []Message `json:"data"`
}

type Message struct {
    From    string `json:"from"`
    To      string `json:"to"`
    Message string `json:"message"`
}

func main() {
    http.HandleFunc("/", Greet)
    http.ListenAndServe(":3000", nil)
}

func Greet(rw http.ResponseWriter, request *http.Request) {
    decoder := json.NewDecoder(request.Body)
    var greetings Greetings
    err := decoder.Decode(&greetings)
    if err != nil {
        panic(err)
    }
    for _, g := range greetings.Greetings {
        fmt.Printf("%s, to %s from %s.\n", g.Greeting, g.To, g.From)
    }

    relationShip := &RelationShip{Messages: greetings.Greetings}
    r, err := json.Marshal(&relationShip)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(r))
}

Here's an example curl request

curl -d '{"data": [{"to":"drew","from":"jo","greeting":"Hey"}, \
  {"to":"lori", "from":"yuri","greeting":"what up?"}]}' \
  http://localhost:3000

I thought maybe I could get away with something like:

relationShip := &RelationShip{Messages: greetings.Greetings}

But it I can't use type []Greeting as type []Message. I'm really new to Go, and statically typed languages in general. Do I iterate through the list of Greetings and push them as new Message items into Messages?

The Point: I'm writing an API that can take an incoming request, and send it to the correct third party API, which will always care about the same data, but may have different keys. So tips on the actual question, and/or also on a better approach are appreciated and welcome :)

1
  • 2
    ` iterate through the list of Greetings and push them as new Message items into Messages` is not a bad idea. Commented May 17, 2016 at 2:40

2 Answers 2

1

As you noticed, you can't use type []Greeting as type []Message. Because they are not the same type. However, there is a way to convert from one type to another, but it requires identical types.

For example, the following would work:

type Message struct {
    From string    `json:"from"`
    To string      `json:"to"`
    Message string `json:"message"`
}

type Greeting struct {
    From string    `json:"from"`
    To string      `json:"to"`
    Message string `json:"message"`
}

func main() {
    mess := Message{"from", "to", "message"}
    fmt.Println(reflect.TypeOf(mess))
    // > Message
    greet := Greeting(mess)
    fmt.Println(reflect.TypeOf(greet))
    // > Greeting
}

However, it requires that the fields are the same, and the json tags as well.

In your case, iterating through greetings and transforming them into messages will work without problems.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, in my case, the point is that the fields aren't the same.
When we say "tag" are we referring to the json keys? and "field" to the struct fields?
Yes, that's it. json:"abcd" are called tags in Go. And you're correct about struct fields too.
0

Based on Jiang YD's comment, I replaced

relationShip := &RelationShip{Messages: greetings.Greetings}

with the following:

var relationShip RelationShip
for _, g := range greetings.Greetings {
    relationShip.Messages = append(
        relationShip.Messages, Message{
            To: g.To, From: g.From, Message: g.Greeting,
        },
    )
}

Which does what I'd like to do. Thanks for the feedback!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.