JohnStephen.19
JohnStephen.19

Reputation: 363

How to decode/unmarshal Request Body into Golang structs and struct slices?

How do I properly unmarshal this in Golang?

{
    "symbol": "ZVZZT.O",
    "params": [{
        "forward": 0,
        "period": 3,
        "ref": "high",
        "indicator": "sma",
        "freq": "day"
    }, {
        "forward": 1,
        "period": 8,
        "ref": "close",
        "indicator": "ema",
        "freq": "week"
    }]
}

into these structs

type Iteration4RequestBody struct {
    Symbol string             `json:"symbol"`
    Params []Iteration4Params `json:"params"`
}

type Iteration4Params struct {
    Forward   int    `json:"forward"`
    Period    int    `json:"period"`
    Ref       string `json:"ref"`
    Indicator string `json:"indicator"`
    Freq      string `json:"freq"`
}

I need to be able to use []Iteration4Params, but right now, this is empty when I decode it

EDIT 2 (NEW CODE I USED)

body, err := ioutil.ReadAll(r.Body)
if err != nil {
    panic(err)
}
var t Iteration4RequestBody
err = json.Unmarshal(body, &t)
if err != nil {
    panic(err)
}
fmt.Println(t)

Result is {ZVZZT.O []}

Edit 3: Works now. Can't remember the last thing I did before it worked though. Never mind. Thanks for all your answers by the way.

Upvotes: 0

Views: 9333

Answers (2)

Massimo Zerbini
Massimo Zerbini

Reputation: 3191

If you want to use a json.Decoder you can loop testing if there are more elements:

for dec.More() {
  var b Iteration4RequestBody
  if err := dec.Decode(&b); err != nil {
     log.Fatal(err)
  } else {
    log.Println(b)
  }
}

https://play.golang.org/p/-dgg9kfjdp8

Upvotes: 1

Marc
Marc

Reputation: 21085

I'm confused about a few things you're doing:

  • using a for when you're decoding a request.Body
  • expecting more than one element
  • not just appending b directly

Dropping the loop and using either json.Unmarshal or json.NewDecoder works fine. I could keep the for loop, and it would still work. You should show the rest of your code, you have a problem elsewhere, either:

  • the request body is empty or already read and closed
  • you're returning the parsed objects in a strange way
  • something else?

Here's working code (without the for loop), showing both possibilities:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "strings"
)

var j = `
{
    "symbol": "ZVZZT.O",
    "params": [{
        "forward": 0,
        "period": 3,
        "ref": "high",
        "indicator": "sma",
        "freq": "day"
    }, {
        "forward": 1,
        "period": 8,
        "ref": "close",
        "indicator": "ema",
        "freq": "week"
    }]
}`

type Iteration4RequestBody struct {
    Symbol string             `json:"symbol"`
    Params []Iteration4Params `json:"params"`
}

type Iteration4Params struct {
    Forward   int    `json:"forward"`
    Period    int    `json:"period"`
    Ref       string `json:"ref"`
    Indicator string `json:"indicator"`
    Freq      string `json:"freq"`
}

func main() {
    // Using json.Unmarshal
    var it Iteration4RequestBody
    err := json.Unmarshal([]byte(j), &it)
    if err != nil {
        panic(err)
    }
    fmt.Println(it)

    // Using a json.Decoder
    var it2 Iteration4RequestBody
    dec := json.NewDecoder(strings.NewReader(j))
    if err := dec.Decode(&it2); err != nil && err != io.EOF {
        panic(err)
    }
    fmt.Println(it2)
}

Outputs:

{ZVZZT.O [{0 3 high sma day} {1 8 close ema week}]}
{ZVZZT.O [{0 3 high sma day} {1 8 close ema week}]}

Upvotes: 4

Related Questions