Request Body is null in Go lang (Postman) - json

I am using Postman to post the json string on localhost. The json string that Iam passing in Postman is :
{
“name”: "foo"
}
However, when I retrieve the data in my test function, the req.Body i get something like this : &{%!s(*io.LimitedReader=&{0xc0820142a0 0}) <nil> %!s(*bufio.Reader=<nil>) %!s(bool=false) %!s(bool=true) {%!s(int32=0) %!s(uint32=0)} %!s(bool=true) %!s(bool=false) %!s(bool=false)}
I wish to get the name:foo in the request body.
My go lang code for the same is :
import (
"encoding/json"
"fmt"
"net/http"
)
type Input struct {
Name string `json:"name"`
}
func test(rw http.ResponseWriter, req *http.Request) {
var t Input
json.NewDecoder(req.Body).Decode(&t)
fmt.Fprintf(rw, "%s\n", req.Body)
}
func main() {
http.HandleFunc("/test", test)
http.ListenAndServe(":8080", nil)
}
Can anyone tell me why I am getting blank data in the req.Body attribute ? Thanks a lot.

Reuqes Body should be empty because you already read all from it. But that not the issue.
From your question, it seem your input is not valid JSON (you have “ which is different with ").
The Decode method will return error, you should check that.
if err := json.NewDecoder(req.Body).Decode(&t); err != nil {
fmt.Println(err)
}

Related

How to convert *elbv2.DescribeLoadBalancersOutput to an JSON in goLang to perform data parsing

I have been trying to work with AWS Go SDK Version 2. I am getting an where I want to convert the response I got from DescribeLoadBalancer() function into a JSON, so that I can parse it and perform further action but when I try to follow how to parse the JSON in go describe here https://blog.alexellis.io/golang-json-api-client/. I get an error in the compiler that I can't convert *elbv2.DescribeLoadBalancersOutput into []byte. I tried different approaches i.e trying to convert *elbv2.DescribeLoadBalancersOutput into string etc but I always get the same error i.e cannot convert *elbv2.DescribeLoadBalancersOutput into the specified type. hence want to understand what would be the best to perform the required action. Here's my code.
package main
import (
"encoding/gob"
"fmt"
"reflect"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/elbv2"
)
type LoadBalancerARN struct {
loadBalancerARN string
}
func main() {
session, error := session.NewSession(&aws.Config{
Region: aws.String("eu-central-1"),
})
if error != nil {
fmt.Printf("Cannot create a session, %v", error)
}
service := elbv2.New(session)
input := &elbv2.DescribeLoadBalancersInput{}
getLoadBalancersJson, error := service.DescribeLoadBalancers(input)
if error != nil {
if aerr, ok := error.(awserr.Error); ok {
switch aerr.Code() {
case elbv2.ErrCodeLoadBalancerNotFoundException:
fmt.Println(elbv2.ErrCodeLoadBalancerNotFoundException, aerr.Error())
default:
fmt.Println(aerr.Error())
}
} else {
fmt.Println(error.Error())
}
return
}
encodinglbJson := gob.NewEncoder(getLoadBalancersJson)
//var arn LoadBalancerARN
fmt.Println(getLoadBalancersJson)
fmt.Println(reflect.TypeOf(getLoadBalancersJson))
}
So, I have figured the above out, best way to do the above is, AWS provide a LoadBalancer function which convert the *elbv2.DescribeLoadBalancersOutput into an object of type *[]elbv2.LoadBalancer and then you can convert that object into the byte array using json.Marshal function and from there you can perform the parsing as needed.
Here's code
type LoadBalancerJSONStructure struct {
LoadBalancerArn string
DNSName string
CanonicalHostedZoneId string
CreatedTime string
LoadBalancerName string
Scheme string
VpcId string
Type string
IpAddressType string
}
response, error := json.Marshal(getLoadBalancers.LoadBalancers)
if error != nil {
fmt.Println("Error, %v", error)
}
fmt.Println(reflect.TypeOf(getLoadBalancers.LoadBalancers))
var lbJson LoadBalancerJSONStructure
err := json.Unmarshal(response, &lbJson)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Struct is: ", lbJson)

using http.PostForm to POST nested json data values?

I've seen the following example of how to use net/http PostForm to send a basic string map as a POST request:
How to send a POST request in Go?
But the data that I need to post is slightly more complicated as it has nested json / nested string maps. An example of the data I need to post:
{"MyAttributes" : {"AttributeOne" : "one", "AttributeTwo":"two"}}
Can net/url Values represent that kind of nested data and/or how do I pass this to net/http PostForm?
It's possible
package main
import (
"encoding/json"
"log"
"net/http"
"net/url"
)
type Attributes struct {
AttributeOne string
AttributeTwo string
}
func main() {
attributes := Attributes{"one", "two"}
data, err := json.Marshal(attributes)
if err != nil {
log.Fatal("bad", err)
}
values := url.Values{}
values.Set("MyAttributes", string(data))
resp, error := http.PostForm("localhost:2021", values)
// use resp and error later
}

Why is my Go server not correctly decoding the JSON it is being sent from the client?

I am working on writing a server in Go for a project, which involves receiving JSON data from a client and sending back a JSON response. When I run the code, any request I make works correctly, but the response is always empty. Here is the code for my server.
type AddPlayerData struct {
name string
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("[ SUCCESS ] Request from ", r.RemoteAddr)
decoder := json.NewDecoder(r.Body)
var data AddPlayerData
err := decoder.Decode(&data)
if err != nil {
panic(err)
}
defer r.Body.Close()
json.NewEncoder(w).Encode(data)
}).Methods("PUT");
log.Fatal(http.ListenAndServe(":8080", router))
}
The requests I am sending are PUT requests formatted as follows:
{
"name": "test-player"
}
I am receiving a response, but it is always empty.
Here the issue is with you json encoding. AddPlayerData struct should export it's fields inorder for json decoder/encoder to work.
Modify your struct to below
type AddPlayerData struct {
Name string `json:"name"`
}

Golang json Unmarshal "unexpected end of JSON input"

I am working on some code to parse the JSON data from an HTTP response. The code I have looks something like this:
type ResultStruct struct {
result []map[string]string
}
var jsonData ResultStruct
err = json.Unmarshal(respBytes, &jsonData)
The json in the respBytes variable looks like this:
{
"result": [
{
"id": "ID 1"
},
{
"id": "ID 2"
}
]
}
However, err is not nil. When I print it out it says unexpected end of JSON input. What is causing this? The JSON seems to valid. Does this error have something to do with my custom struct?
Thanks in advance!
The unexpected end of JSON input is the result of a syntax error in the JSON input (likely a missing ", }, or ]). The error does not depend on the type of the value that you are decoding to.
I ran the code with the example JSON input on the playground. It runs without error.
The code does not decode anything because the result field is not exported. If you export the result field:
type ResultStruct struct {
Result []map[string]string
}
then the input is decoded as shown in this playground example.
I suspect that you are not reading the entire response body in your application. I suggest decoding the JSON input using:
err := json.NewDecoder(resp.Body).Decode(&jsonData)
The decoder reads directly from the response body.
You can also get this error if you're using json.RawMessage in an unexported field. For example, the following code produces the same error:
package main
import (
"encoding/json"
"fmt"
)
type MyJson struct {
Foo bool `json:"foo"`
bar json.RawMessage `json:"bar"`
}
type Bar struct {
X int `json:"x"`
}
var respBytes = []byte(`
{
"foo": true,
"bar": { "x": 10 }
}`)
func main() {
var myJson MyJson
err := json.Unmarshal(respBytes, &myJson)
if err != nil {
fmt.Println(err)
return
}
myBar := new(Bar)
err = json.Unmarshal(myJson.bar, myBar)
fmt.Println(err)
}
If you export "MyJson.bar" field (e.g. -> "MyJson.Bar", then the code works.
it is not the case here; but if you are getting this error loading json from a file it Will occur if the byte slice for the buffer is not initialized the the byte size of the file. [when you're new like me that happens! ] Since this is the first search result I got it still took some digging to figure out. In this use case the error is a bit misleading.
type GenesisResultStruct []GenesisField
fileinfo, _ := genesis.Stat()
bs := make([]byte, fileinfo.Size())
//bs := []byte {} // wrong!!
_, error := genesis.Read(bs)
if error != nil {
fmt.Println("genesis read error: ", error)
os.Exit(1)
}
var jsonData GenesisResultStruct
eGen = json.Unmarshal(bs, &jsonData)
if eGen != nil {
fmt.Println("genesis unmarshal error: ", eGen)
os.Exit(1)
}
Faced the same issue today.
You can also get this error if the respBytes is nil or there are no brackets [] if you are unmarshalling it to a slice.
In that case, you need to explicitly set respBytes.
As you are unmarshalling it to a slice, brackets [] are expected in the byte-slice
if src == nil {
src = []byte("[]")
}

Handling JSON Post Request in Go

So I have the following, which seems incredibly hacky, and I've been thinking to myself that Go has better designed libraries than this, but I can't find an example of Go handling a POST request of JSON data. They are all form POSTs.
Here is an example request: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test
And here is the code, with the logs embedded:
package main
import (
"encoding/json"
"log"
"net/http"
)
type test_struct struct {
Test string
}
func test(rw http.ResponseWriter, req *http.Request) {
req.ParseForm()
log.Println(req.Form)
//LOG: map[{"test": "that"}:[]]
var t test_struct
for key, _ := range req.Form {
log.Println(key)
//LOG: {"test": "that"}
err := json.Unmarshal([]byte(key), &t)
if err != nil {
log.Println(err.Error())
}
}
log.Println(t.Test)
//LOG: that
}
func main() {
http.HandleFunc("/test", test)
log.Fatal(http.ListenAndServe(":8082", nil))
}
There's got to be a better way, right? I'm just stumped in finding what the best practice could be.
(Go is also known as Golang to the search engines, and mentioned here so others can find it.)
Please use json.Decoder instead of json.Unmarshal.
func test(rw http.ResponseWriter, req *http.Request) {
decoder := json.NewDecoder(req.Body)
var t test_struct
err := decoder.Decode(&t)
if err != nil {
panic(err)
}
log.Println(t.Test)
}
You need to read from req.Body. The ParseForm method is reading from the req.Body and then parsing it in standard HTTP encoded format. What you want is to read the body and parse it in JSON format.
Here's your code updated.
package main
import (
"encoding/json"
"log"
"net/http"
"io/ioutil"
)
type test_struct struct {
Test string
}
func test(rw http.ResponseWriter, req *http.Request) {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
var t test_struct
err = json.Unmarshal(body, &t)
if err != nil {
panic(err)
}
log.Println(t.Test)
}
func main() {
http.HandleFunc("/test", test)
log.Fatal(http.ListenAndServe(":8082", nil))
}
There are two reasons why json.Decoder should be preferred over json.Unmarshal - that are not addressed in the most popular answer from 2013:
February 2018, go 1.10 introduced a new method json.Decoder.DisallowUnknownFields() which addresses the concern of detecting unwanted JSON-input
req.Body is already an io.Reader. Reading its entire contents and then performing json.Unmarshal wastes resources if the stream was, say a 10MB block of invalid JSON. Parsing the request body, with json.Decoder, as it streams in would trigger an early parse error if invalid JSON was encountered. Processing I/O streams in realtime is the preferred go-way.
Addressing some of the user comments about detecting bad user input:
To enforce mandatory fields, and other sanitation checks, try:
d := json.NewDecoder(req.Body)
d.DisallowUnknownFields() // catch unwanted fields
// anonymous struct type: handy for one-time use
t := struct {
Test *string `json:"test"` // pointer so we can test for field absence
}{}
err := d.Decode(&t)
if err != nil {
// bad JSON or unrecognized json field
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
if t.Test == nil {
http.Error(rw, "missing field 'test' from JSON object", http.StatusBadRequest)
return
}
// optional extra check
if d.More() {
http.Error(rw, "extraneous data after JSON object", http.StatusBadRequest)
return
}
// got the input we expected: no more, no less
log.Println(*t.Test)
Playground
Typical output:
$ curl -X POST -d "{}" http://localhost:8082/strict_test
expected json field 'test'
$ curl -X POST -d "{\"Test\":\"maybe?\",\"Unwanted\":\"1\"}" http://localhost:8082/strict_test
json: unknown field "Unwanted"
$ curl -X POST -d "{\"Test\":\"oops\"}g4rB4g3##$%^&*" http://localhost:8082/strict_test
extraneous data after JSON
$ curl -X POST -d "{\"Test\":\"Works\"}" http://localhost:8082/strict_test
log: 2019/03/07 16:03:13 Works
I was driving myself crazy with this exact problem. My JSON Marshaller and Unmarshaller were not populating my Go struct. Then I found the solution at https://eager.io/blog/go-and-json:
"As with all structs in Go, it’s important to remember that only
fields with a capital first letter are visible to external programs
like the JSON Marshaller."
After that, my Marshaller and Unmarshaller worked perfectly!
I found the following example from the docs really helpful (source here).
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"strings"
)
func main() {
const jsonStream = `
{"Name": "Ed", "Text": "Knock knock."}
{"Name": "Sam", "Text": "Who's there?"}
{"Name": "Ed", "Text": "Go fmt."}
{"Name": "Sam", "Text": "Go fmt who?"}
{"Name": "Ed", "Text": "Go fmt yourself!"}
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
var m Message
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %s\n", m.Name, m.Text)
}
}
The key here being that the OP was looking to decode
type test_struct struct {
Test string
}
...in which case we would drop the const jsonStream, and replace the Message struct with the test_struct:
func test(rw http.ResponseWriter, req *http.Request) {
dec := json.NewDecoder(req.Body)
for {
var t test_struct
if err := dec.Decode(&t); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
log.Printf("%s\n", t.Test)
}
}
Update: I would also add that this post provides some great data about responding with JSON as well. The author explains struct tags, which I was not aware of.
Since JSON does not normally look like {"Test": "test", "SomeKey": "SomeVal"}, but rather {"test": "test", "somekey": "some value"}, you can restructure your struct like this:
type test_struct struct {
Test string `json:"test"`
SomeKey string `json:"some-key"`
}
...and now your handler will parse JSON using "some-key" as opposed to "SomeKey" (which you will be using internally).
I like to define custom structs locally. So:
// my handler func
func addImage(w http.ResponseWriter, r *http.Request) {
// define custom type
type Input struct {
Url string `json:"url"`
Name string `json:"name"`
Priority int8 `json:"priority"`
}
// define a var
var input Input
// decode input or return error
err := json.NewDecoder(r.Body).Decode(&input)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Decode error! please check your JSON formating.")
return
}
// print user inputs
fmt.Fprintf(w, "Inputed name: %s", input.Name)
}
type test struct {
Test string `json:"test"`
}
func test(w http.ResponseWriter, req *http.Request) {
var t test_struct
body, _ := ioutil.ReadAll(req.Body)
json.Unmarshal(body, &t)
fmt.Println(t)
}