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.
", 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 :)
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!
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.