jsonbody

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 1, 2020 License: MIT Imports: 9 Imported by: 0

README

GoDoc

jsonbody

jsonbody is a Golang middleware library that makes receiving JSON web request bodies, validating them, and sending JSON response bodies easy.

Installation

Just run go get github.com/jasonccox/jsonbody and import github.com/jasonccox/jsonbody in your code.

Examples

Using the Middleware in a Route

The following code creates a middleware function that will ensure all requests to the /turtle route have a body matching the given schema.

import "github.com/jasonccox/jsonbody"

func main() {

	// create the middleware function - a func(next http.Handler) http.Handler
    middleware := jsonbody.NewMiddleware(`{
        "name": "",
        "age": 0,
        "details": {
            "?species": "",
            "aquatic": false
        },
        "children": ["name"]
    }`)

	// use the middleware in the route
	http.Handle("/turtle", middleware(myHandler{})

	...
}
Handling the Request

The following code uses the jsonbody.Reader and jsonbody.Writer to handle a POST request.

import "github.com/jasonccox/jsonbody"

type myHandler struct {}

func (h myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	jsonWriter, ok := w.(jsonbody.Writer)
	if !ok {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	jsonReader, ok := r.Body.(jsonbody.Reader)
	if !ok {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	jsonBody := jsonReader.JSON() // returns a map[string]interface{} representing the request body

	turt := turtle{
		name:     jsonBody["name"].(string), // we can safely assert the type because the middleware already checked it
		age:      jsonBody["age"].(float64), // JSON numbers are represented as float64
		children: jsonBody["children"].([]string)
	}

	turtDetails := jsonBody["details"].(map[string]interface{}) // JSON objects are represented as map[string]interface{}
	turt.aquatic = turtDetails["aquatic"].(bool)

	if s, ok := turtDetails["species"]; ok { // details.species was optional, so we need to make sure it was set before using it
		turt.species = s.(string)
	}

	if turt.age < 0.0 {
		jsonWriter.WriteErrors(http.StatusBadRequest, "age must be positive") // sends back an error body
		return
	}

	// do some processing here...

	jsonWriter.WriteJSON(http.StatusCreated, turt) // converts turt to JSON and writes it as the response body
}

Documentation

For more in-depth information, check out the godoc.

Documentation

Overview

Package jsonbody is a Golang middleware library that makes receiving JSON web request bodies, validating them, and sending JSON response bodies easy.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewMiddleware

func NewMiddleware(schemaJSON string) func(next http.Handler) http.Handler

NewMiddleware creates a middleware that converts the request body to a map and allows the response to be written as JSON. When the middleware calls next.ServeHTTP(), it passes it a Writer and a *http.Request with Body set as a Reader. See documentation for Reader and Writer regarding accessing the request body and writing to the response body.

The middleware can also optionally validate the content type and request body by checking that its structure matches a pre-defined schema. If the request body does not match the schema, a 400 response with the following JSON body will be sent:

{
	"errors": [ <list of error strings> ]
}

The schemaJSON should essentially be a sample request body. All keys in the schemaJSON (unless they begin with a question mark) will be expected to be present in request bodies that pass through the middleware. Additionally, all values will be expected to have the same type as the values in the schema. Arrays in the schema need only have one element in them against which all array elements in the real request will be verified. Finally, an empty object or empty array in the schema indicates that the object/array in the requests must be present but can have any contents. See the example below for further clarification.

Setting schemaJSON to "" (the empty string) indicates that any JSON body (including none at all) and any content type should be accepted.

Example Schema (don't actually include comments in yours)

	{
		"title": "",        // body must contain a key "title" with a string value
		"upvotes": 0,       // body must contain a key "upvotes" with a number value
		"?public": false,   // body may contain a key "public" with a boolean value
		"comments": [       // body must contain a key "comments" with an array value
			""              // each element in the "comments" array must be a string
		],
		"author": {         // body must contain a key "author" with an object value
			"name": "",	    // "author" object must contain a key "name" with a
                         // string value
			...
		},
		"metadata": {},     // body must contain a key "metadata" with an object
		                    // value, but the value can contain any keys, or none at
                         // all
		"tags": [],         // body must contain a key "tags" with an array value,
		                    // but the elements can be of any type
		...
	}

Types

type Reader

type Reader struct {
	io.ReadCloser
	// contains filtered or unexported fields
}

Reader is an extension of a generic io.Reader. It provides a method for retrieving the JSON request body as a map[string]interface{}.

func (Reader) JSON

func (r Reader) JSON() map[string]interface{}

JSON returns a a map[string]interface{} representing the request body. See the documentation for encoding/json regarding how the map represents the JSON data.

type Writer

type Writer struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

Writer is an extension of a generic http.ResponseWriter. It provides methods for writing an object to the response body as JSON and for easily writing errors to the response body.

func (*Writer) WriteErrors

func (w *Writer) WriteErrors(statusCode int, errs ...string) error

WriteErrors encodes the given errors as a JSON array assigned to the key "errors" and sends it as the response body. This method or WriteJSON can only be called once, unless they return an error.

func (*Writer) WriteJSON

func (w *Writer) WriteJSON(statusCode int, body interface{}) error

WriteJSON encodes an object as JSON and sends it as the response body, along with the Content-Type header. This method or WriteErrors can only be called once, unless they return an error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL