在使用Gorilla的Go ReST服务中处理JSON

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.
}

Playground link

(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)
    }
}

playground