Skip to content

Instantly share code, notes, and snippets.

@andreagrandi
Created August 19, 2014 13:28
Show Gist options
  • Star 63 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save andreagrandi/97263aaf7f9344d3ffe6 to your computer and use it in GitHub Desktop.
Save andreagrandi/97263aaf7f9344d3ffe6 to your computer and use it in GitHub Desktop.
Parse a JSON http POST in GoLang
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type test_struct struct {
Test string
}
func parseGhPost(rw http.ResponseWriter, request *http.Request) {
decoder := json.NewDecoder(request.Body)
var t test_struct
err := decoder.Decode(&t)
if err != nil {
panic(err)
}
fmt.Println(t.Test)
}
func main() {
http.HandleFunc("/", parseGhPost)
http.ListenAndServe(":8080", nil)
}
@andreagrandi
Copy link
Author

Test it with: curl -X POST -d "{"test": "that"}" http://localhost:8080

@oxfordyang2016
Copy link

thank you

@drewlesueur
Copy link

Don't you need to close the request.Body?

@drewlesueur
Copy link

Nevermind. I read in the docs that

The Server will close the request body. The ServeHTTP Handler does not need to.

Thanks for posting the example.

https://golang.org/pkg/net/http/#Request

@marcuxyz
Copy link

invalid character 't' looking for beginning of object key string

@ottaz
Copy link

ottaz commented Sep 6, 2017

try curl -X POST -d "{\"test\": \"that\"}" http://localhost:8080

@fahadhk
Copy link

fahadhk commented Aug 22, 2018

curl -X POST -d '{"test": "that"}' http://localhost:8080

@handle2001
Copy link

handle2001 commented Dec 24, 2018

I get an empty response when running this:
`$ curl -X POST -d "{"test":"something"}" http://localhost:8080

$ `

`$ ./parse_json_post

`

EDIT: Apparently the keyname does matter, but it's not intuitive (for me at least) that the struct member is capitalized and the json key name is not.

@404UsernameNotFound404
Copy link

How would you tackle parsing different kinds of request. I am struggling passing in a struct to the function.

@harshitsinghai77
Copy link

harshitsinghai77 commented Nov 3, 2020

Don't forget

defer r.Body.Close()

Example

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
        "time"

	"github.com/gorilla/mux"
)

type player struct {
	Name string
	Club string
	Age  uint8
}

func mainLogic(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		var tempPlayer player
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&tempPlayer)

		if err != nil {
			panic(err)
		}
		defer r.Body.Close()

		fmt.Printf("Got %s age %d club %s\n", tempPlayer.Name, tempPlayer.Age, tempPlayer.Club)
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(tempPlayer)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Method not allowed."))
	}
}

func main() {
	r := mux.NewRouter()

	r.HandleFunc("/", mainLogic).Methods("POST")
	srv := &http.Server{
		Handler:      r,
		Addr:         "localhost:8000",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}

	log.Fatal(srv.ListenAndServe())
}

@harshitsinghai77
Copy link

Go JSON content-type using the middleware

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
)

type player struct {
	Name string
	Club string
	Age  uint8
}

func middleware(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Executing Content-type middleware before the request phase!")

		if r.Header.Get("Content-type") != "application/json" {
			w.WriteHeader(http.StatusUnsupportedMediaType)
			w.Write([]byte("415 - Unsupported Media Type. Only JSON files are allowed"))
			return
		}

		// Pass control back to the handler
		handler.ServeHTTP(w, r)
	})
}

func mainLogic(w http.ResponseWriter, r *http.Request) {
	// Business logic here
	if r.Method == "POST" {
		fmt.Println("INSIDE LOGIC")
		var tempPlayer player
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&tempPlayer)

		if err != nil {
			panic(err)
		}
		defer r.Body.Close()

		fmt.Printf("Got %s age %d club %s\n", tempPlayer.Name, tempPlayer.Age, tempPlayer.Club)
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(tempPlayer)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Method not allowed."))
	}
}

func main() {
	r := mux.NewRouter()

	r.HandleFunc("/", mainLogic).Methods("POST")
	r.Use(middleware)

	srv := &http.Server{
		Handler:      r,
		Addr:         "localhost:8000",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}

	log.Fatal(srv.ListenAndServe())
}

A simple middleware function to check if the POST request is in JSON format.

@CheenaT
Copy link

CheenaT commented Dec 8, 2020

invalid character 't' looking for beginning of object key string

I fixed it by replacing first and last double quotes to single quotes: -d "{"test": "that"}" -> -d '{"test": "that"}'

@omankame
Copy link

omankame commented Feb 4, 2021

Thank you. It helped me to resolved issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment