Pragmatism in the real world

Handling JSON data errors in Slim 3

When you send JSON data into a Slim Framework application with a content-type of application/json, then Slim will decode it for you if you use getParsedBody():

$app->post("/", function ($request, $response, $args) {
    $input = $request->getParsedBody();

    var_dump($input);exit;
});

Using curl to test:

$ curl -H "Content-Type: application/json" http://localhost:8888 -d '{"foo": "bar"}'
array(1) {
  'foo' =>
  string(3) "bar"
}

If there’s an error however, you get this:

$ curl -H "Content-Type: application/json" http://localhost:8888 -d '{foo: bar}'
NULL

If you care about this, you can use json_last_error_msg() and return an error:

$app->post("/", function ($request, $response, $args) {
    $input = $request->getParsedBody();
    if ($input === null) {
        return $response->withJson(
            ['error_decoding_json' => json_last_error_msg()],
            400,
            JSON_PRETTY_PRINT
        );
    }

    var_dump($input);exit;
});

(note – in real code, you should check that the Accept header was a JSON one…)

Don’t forget the JSON_PRETTY_PRINT as a human is going to be reading this error, so make it easier for them.

Use jsonlint for more information

If you really want to provide great diagnostics, then use jsonlint:

$ composer require seld/jsonlint

Update your handler like this:

$app->post("/", function ($request, $response, $args) {
    $input = $request->getParsedBody();
    if ($input === null) {
        $parser = new \Seld\JsonLint\JsonParser();
        $result = $parser->lint($input);
        if ($result instanceof \Seld\JsonLint\ParsingException) {
            return $response->withJson(
                ['error_decoding_json' => $result->getMessage()],
                400,
                JSON_PRETTY_PRINT
            );
        }
    }

    var_dump($input);exit;
});

(lint() will return NULL or a ParsingException, so we don’t need to test for anything else.)

The result looks like this:

$ curl -H "Content-Type: application/json" http://localhost:8888 -d '{foo: bar}'
{
    "error_decoding_json": "Parse error on line 1:\n\n^\nExpected one of: 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['"
}

This is much more informative!

One thought on “Handling JSON data errors in Slim 3

  1. I think this should be something like this:

    "`
    class JsonLintMiddleware {

    public function __invoke(Request $request, Response $response, $next) {
    $input = $request->getBody();
    $parser = new JsonParser();
    $result = $parser->lint($input);
    if ($result instanceof ParsingException) {
    return $response->withJson(
    ['message' => $result->getMessage()],
    400,
    JSON_PRETTY_PRINT
    );
    }
    $response = $next($request, $response);
    return $response;
    }
    }

    "`

Comments are closed.