Sending a JSON encoded entity to a RESTful API is a common need, and a JSON payload is actually pretty slick and convenient. It eases the pain of form-encoded strings when sending post data, and makes it easier to structure complex data that’s more readable. It can also make documentation easier to follow when you share cURL examples of making requests to your API. JSON is much easier for readers to digest compared to form encoded request params.

So how do we do it in Lumen? I will show you a couple ways we can read JSON data and a middleware that can make it easy to support both Content-Type: application/json as well as the traditional Content-Type: application/x-www-form-urlencoded without polluting the controller with content-type specific logic.

To illustrate, let’s say you are accepting a POST request to create a new blog post in your API and allowing JSON-encoded requests:

curl http://example.com/posts \
  -d '{"title": "My First Post!","body": "This is my first blog post!"}' \
  -H 'Content-Type: application/json'

To read the data in a Lumen route closure/controller, you can use the Illuminate\Http\Request::json() method like so:

This approach works and you can easily start accepting a JSON payload, however, I prefer a different approach to remove the assumption that only JSON is supported, or worse yet, checking in the controller:

We can handle this more elegantly with a middleware:

Now you can get all request data in the same way regardless of how the data was submitted:

Don’t forget to configure the middleware as a global middleware!

Now the middleware will run before each request and and populate the request with JSON data in the same way you’d expect to accept normal POST data!