I have a Go ReST service that receives JSON, and I need to edit the JSON so I may make two different structs.
My structs:
type Interaction struct{
DrugName string `json:"drugName"`
SeverityLevel string `json:"severityLevel"`
Summary string `json:"summary"`
}
type Drug struct {
Name string `json:"drugName"`
Dosages []string `json:"dosages"`
Interactions []Interaction `json:"interactions"`
}
Example JSON being sent:
{"drugName":"foo","dosages":["dos1"],"interactions":[["advil","high","summaryForAdvil"]]}
The ReST service:
func CreateDrug(w http.ResponseWriter, r *http.Request) {
//I verified the received JSON by printing out the bytes:
bytes, _ := ioutil.ReadAll(r.Body)
}
My goal is the make two different JSONs in the CreateDrug function so I may make the two different structs, Drug and Interaction:
{"drugName":"foo","dosages":["dos1"]}
{"drugName":"advil", "severityLevel":"high", "summary":"summaryForAdvil"}
In Go, in this function, how do I use the received JSON to make two new JSONs?
Unmarshal the request to a struct matching the structure of the request, copy values to the structs you have defined, and marshal to create the result.
func CreateDrug(w http.ResponseWriter, r *http.Request) {
// Unmarshal request to value matching the structure of the incoming JSON
var v struct {
DrugName string
Dosages []string
Interactions [][3]string
}
if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
// handle error
}
// Copy to new struct values.
var interactions []Interaction
for _, i := range v.Interactions {
interactions = append(interactions, Interaction{DrugName: i[0], SeverityLevel: i[1], Summary: i[2]})
}
drug := &Drug{Name: v.DrugName, Dosages: v.Dosages, Interactions: interactions}
// Marshal back to JSON.
data, err := json.Marshal(drug)
if err != nil {
// handle error
}
// Do something with data.
}
(I am assuming that you want a single JSON value for Drug with the Interactions field filled in. If that's not what you want, marshal the Drug and Interactions values separately.)
You can use json.Encoder
and output multiple json structs to a stream, you just have to decode the input json, here's a simple example:
type restValue struct {
Name string `json:"drugName"`
Dosages []string `json:"dosages"`
Interactions [][3]string `json:"interactions"`
}
func main() {
d := []byte(`{"drugName":"foo","dosages":["dos1"],"interactions":[["advil","high","summaryForAdvil"]]}`)
var v restValue
if err := json.Unmarshal(d, &v); err != nil {
panic(err)
}
interactions := make([]Interaction, 0, len(v.Interactions))
for _, in := range v.Interactions {
interactions = append(interactions, Interaction{in[0], in[1], in[2]})
}
drug := &Drug{Name: v.Name, Dosages: v.Dosages, Interactions: interactions}
enc := json.NewEncoder(os.Stdout)
// if you want the whole Drug struct
enc.Encode(drug)
// or if you want 2 different ones:
drug = &Drug{Name: v.Name, Dosages: v.Dosages}
enc.Encode(drug)
for _, in := range interactions {
enc.Encode(in)
}
}