Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying handle bad json data when parsed through json_decode(). I'm using the following script:

if(!json_decode($_POST)) {
  echo "bad json data!";
  exit;

If $_POST equals:

'{ bar: "baz" }'

Then json_decode handles the error fine and spits out "bad json data!"; However, if I set $_POST to something like "invalid data", it gives me:

Warning: json_decode() expects parameter 1 to be string, array given in C:\server\www\myserver.dev\public_html\rivrUI\public_home\index.php  on line 6
bad json data!

Do I need to write a custom script to detect valid json data, or is there some other nifty way to detect this?

$_POST is always an array containing the x-www-form-urlencoded parameters passed via POST. How do you send your data to your PHP script? – Gumbo Feb 27, 2010 at 16:58 The included json functions in PHP are not much help. They have a lot of issues. Take a look at json.org to find a good library. – whiskeysierra Feb 27, 2010 at 17:02
  • it returns the data, or null when there is an error
  • it can also return null when there is no error : when the JSON string contains null
  • it raises a warning where there is a warning -- warning that you want to make disappear.
  • To solve the warning problem, a solution would be to use the @ operator (I don't often recommend using it, as it makes debuging a lot more harder... But here, there is not much of a choice) :

    $_POST = array(
        'bad data'
    $data = @json_decode($_POST);
    

    You'd then have to test if $data is null -- and, to avoid the case in which json_decode returns null for null in the JSON string, you could check json_last_error, which (quoting) :

    Returns the last error (if any) occurred by last JSON parsing.

    Which means you'd have to use some code like the following :

    if ($data === null
        && json_last_error() !== JSON_ERROR_NONE) {
        echo "incorrect data";
                    As Harry Bosch pointed out in another answer, you need only check for JSON_ERROR_NONE !== json_last_error()
    – alttag
                    Apr 12, 2019 at 2:13
                    PHP 8 returns the error if a function fails with "@" (instead of returning false as before).
    – migli
                    Jan 25 at 7:23
    catch (\JsonException $exception) {  
      echo $exception->getMessage(); // displays "Syntax error"  
                    I received an exception: "Warning: Use of undefined constant JSON_THROW_ON_ERROR - assumed 'JSON_THROW_ON_ERROR' (this will throw an Error in a future version of PHP) in <file_path>
    – domdambrogia
                    Apr 28, 2020 at 1:35
    

    You can also use json_last_error : http://php.net/manual/en/function.json-last-error.php

    which as documentation says :

    Returns the last error (if any) occurred during the last JSON encoding/decoding.

    here is an example

    json_decode($string);
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
                    This is completely unnecessary in PHP 5.5 with php.net/manual/en/function.json-last-error-msg.php
    – vvondra
                    Mar 4, 2015 at 0:16
                    You could do something like this with json_last_error_msg: if (JSON_ERROR_NONE !== json_last_error()) throw new Exception(json_last_error_msg());
    – A1rPun
                    Sep 3, 2019 at 20:45
     * @return array|string|int|bool|float
     * @throws RuntimeException if the response body is not in JSON format
    public function json()
        $data = json_decode((string) $this->body, true);
        if (JSON_ERROR_NONE !== json_last_error()) {
            throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
        return $data === null ? array() : $data;
    

    I just broke my head over a json syntax error in what appeared to be perfect json: {"test1":"car", "test2":"auto"} from a url encoded string.

    But in my case some of the above was html encoded, as adding html_entity_decode($string) did the trick.

    $ft = json_decode(html_entity_decode(urldecode(filter_input(INPUT_GET, 'ft', FILTER_SANITIZE_STRING))));
    

    Hopefully this will save someone else some time.

    I just spent an hour going through all the possible solutions on this page. I took the liberty of collective all these possible solutions into one function, to make it quicker and easier to try and debug.

    I hope it can be of use to someone else.

    * Decontaminate text * Primary sources: * - https://stackoverflow.com/questions/17219916/json-decode-returns-json-error-syntax-but-online-formatter-says-the-json-is-ok * - https://stackoverflow.com/questions/2348152/detect-bad-json-data-in-php-json-decode function decontaminate_text( $text, $remove_tags = true, $remove_line_breaks = true, $remove_BOM = true, $ensure_utf8_encoding = true, $ensure_quotes_are_properly_displayed = true, $decode_html_entities = true if ( '' != $text && is_string( $text ) ) { $text = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $text ); $text = str_replace(']]>', ']]&gt;', $text); if( $remove_tags ){ // Which tags to allow (none!) // $text = strip_tags($text, '<p>,<strong>,<span>,<a>'); $text = strip_tags($text, ''); if( $remove_line_breaks ){ $text = preg_replace('/[\r\n\t ]+/', ' ', $text); $text = trim( $text ); if( $remove_BOM ){ // Source: https://stackoverflow.com/a/31594983/1766219 if( 0 === strpos( bin2hex( $text ), 'efbbbf' ) ){ $text = substr( $text, 3 ); if( $ensure_utf8_encoding ){ // Check if UTF8-encoding if( utf8_encode( utf8_decode( $text ) ) != $text ){ $text = mb_convert_encoding( $text, 'utf-8', 'utf-8' ); if( $ensure_quotes_are_properly_displayed ){ $text = str_replace('&quot;', '"', $text); if( $decode_html_entities ){ $text = html_entity_decode( $text ); * Other things to try * - the chr-function: https://stackoverflow.com/a/20845642/1766219 * - stripslashes (THIS ONE BROKE MY JSON DECODING, AFTER IT STARTED WORKING, THOUGH): https://stackoverflow.com/a/28540745/1766219 * - This (improved?) JSON-decoder didn't help me, but it sure looks fancy: https://stackoverflow.com/a/43694325/1766219 return $text; // Example use $text = decontaminate_text( $text ); // $text = decontaminate_text( $text, false ); // Debug attempt 1 // $text = decontaminate_text( $text, false, false ); // Debug attempt 2 // $text = decontaminate_text( $text, false, false, false ); // Debug attempt 3 $decoded_text = json_decode( $text, true ); echo json_last_error_msg() . ' - ' . json_last_error();

    I'll maintain it here: https://github.com/zethodderskov/decontaminate-text-in-php/blob/master/decontaminate-text-preparing-it-for-json-decode.php

    public static function custom_json_decode($json_text) { $decoded_array = json_decode($json_text, TRUE); switch (json_last_error()) { case JSON_ERROR_NONE: return array( "status" => 0, "value" => $decoded_array case JSON_ERROR_DEPTH: return array( "status" => 1, "value" => 'Maximum stack depth exceeded' case JSON_ERROR_STATE_MISMATCH: return array( "status" => 1, "value" => 'Underflow or the modes mismatch' case JSON_ERROR_CTRL_CHAR: return array( "status" => 1, "value" => 'Unexpected control character found' case JSON_ERROR_SYNTAX: return array( "status" => 1, "value" => 'Syntax error, malformed JSON' case JSON_ERROR_UTF8: return array( "status" => 1, "value" => 'Malformed UTF-8 characters, possibly incorrectly encoded' default: return array( "status" => 1, "value" => 'Unknown error' class JsonUtil { static function decode($json, $associative = null, $depth = null) { if (strtolower(trim($json)) === "null") { return null; if (is_null($associative)) { $res = json_decode($json); else { if (is_null($depth)) { $depth = 512; $res = json_decode($json, $associative, $depth); if (is_null($res)) { throw new Exception("Unable to decode JSON"); return $res;

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.