0

My go application needs to make a post request and a map will be put in the request body.

For now I'm firstly making the map to json string, and converting it to io.Reader.

I'm wondering if there is any way that I can skip json.Marshal step?

var data map[string]interface{} {
        "a": 1,
        "b": "cdef",
        ...
}

jsonData, err := json.Marshal(data)

resp, err := http.Post(
        "localhost:3000", "application/json", bytes.NewReader(jsonData))
Zombo
  • 1
  • 62
  • 391
  • 407
call-me-corgi
  • 193
  • 4
  • 10
  • 4
    You have to encode the map *somehow* and if the server expects JSON you cannot skip the JSON encoding, obviously. – Peter Mar 12 '21 at 09:36

2 Answers2

6

Here is another approach:

package main

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

func main() {
   m, b := map[string]interface{}{"a": 1, "b": "cdef"}, new(bytes.Buffer)
   json.NewEncoder(b).Encode(m)
   http.Post("http://example.com", "application/json", b)
}

Note that we still have to encode the JSON, but do get to omit the NewReader call.

https://golang.org/pkg/encoding/json#Encoder.Encode

Zombo
  • 1
  • 62
  • 391
  • 407
0

No, you cannot skip serializing your map.

Post expects a reader because it wants to read a stream of bytes. A map is not a stream of bytes - it's an in-memory data structure. You could serialize your map using many ways: gob, XML, JSON, YAML, protobuf, your-custom-format, etc. It all depends on what your server expects.

If your server expects JSON, you'll have to serialize it into JSON and send that JSON buffer.

If you expect to do this a lot and are bothered by the calls to Marshal, how about encapsulating this into a function you can invoke?

See also other questions/answers related to this:

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412