26

All my AJAX requests are in json format which are being parsed in javascript.

How can i prevent null values being displayed in an HTML page without needing to write an if-statement in javascript for each json value?

Or should i write a custom PHP function to encode an array to json instead of using json_encode() so it doesn't display 'null' ?

Slartibartfast
  • 8,735
  • 6
  • 41
  • 45
Sobek
  • 291
  • 1
  • 4
  • 9

8 Answers8

31

In server side with PHP,

You can use array_filter before json_encode.

array_filter without second argument removes null elements of entry array, example :

$object= array(
             0 => 'foo',
             1 => false,
             2 => -1,
             3 => null,
             4 => ''
          );

$object = (object) array_filter((array) $object);
$result = json_encode($object);

The $result contains:

{"0":"foo","2":-1}

As you see, the null elements are removed.

masoud
  • 55,379
  • 16
  • 141
  • 208
  • 7
    thanks for your answer but this won't work for multidimensional arrays, and removing the keys will result in 'undefined' values – Sobek Oct 13 '11 at 08:11
  • 2
    @Sobek, BTW, You can't remove a value and keep the key at the same time. – rustyx Jan 19 '13 at 20:15
21

I'm going to add to the accepted answer because that will only work if you have a 1 dimensional object or array. If there is any array or object nesting then in order to get the accepted solution to work, you must create some sort of recursive array filter. Not ideal.

The best solution my colleague and I came up with was to actually perform a regular expression on the JSON string before it was returned from the server.

$json = json_encode($complexObject);
echo preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $json);

The regular expression will remove all places in the string of the form ,"key":null including any whitespace between the leading comma and the start of the key. It will also match "key":null, afterwards to make sure that no null values were found at the beginning of a JSON object.

This isn't an ideal solution but it's far better than creating a recursive array filter given an object could be several dimensions deep. A better solution would be if json_encode had a flag that let you specify if you wanted null entries to remain in the output string.

Jim S.
  • 1,130
  • 1
  • 9
  • 13
  • In the end this is what worked for me. I had multidimensional JSON objects. I agree that this would be nice if `json_encode` natively had support for it, but I highly doubt that'll ever happen. PHP tends to be weak with multidimensional anything, at least in my experience. – Muhammad Abdul-Rahim Apr 21 '16 at 22:57
  • 3
    This worked for me, but I added ` ?` before each `null` to account for when JSON_PRETTY_PRINT is set and there's a space between the key and value. – colincameron Jan 27 '17 at 14:50
  • This doesn't work for me for some reason. – Drewdavid May 25 '21 at 16:35
9

To remove only NULL, but keep FALSE, '', and 0:

function is_not_null($var)
{
    return !is_null($var);
}

echo json_encode(array_filter((array) $object, 'is_not_null'));
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
5
public function __toString() {
    $obj = clone $this;
    $keys = get_object_vars($obj);
    foreach ($keys as $key => $value) {
        if (!$value) {
            unset($obj->{$key});
        }
    }
    return json_encode($obj);
}
baiyangliu
  • 61
  • 1
  • 3
  • 3
    Maybe you may add some comment and explanation, teach us! Just placing your code has less added value. – Honza Zidek May 11 '14 at 15:28
  • @HonzaZidek __toString() is a magic method that gets called when an object is casted to a string. What is doing is returning a copy of the called object, but first looping through it and unsetting all of its attributes. You would do something like var_dump((string) $object). – Parris Varney Jul 31 '14 at 15:35
1

What about using the native JSON.stringify method on the javascript side? You can set, a second parameter, a function to remove keys with a null value. If you return undefined, the property is not included in the output JSON string (check the documentation for "the replacer parameter" at https://developer.mozilla.org/en-US/docs/Using_native_JSON#The_replacer_parameter).

function removeNulls(obj) {
    var str = JSON.stringify(obj, function(key, val) {
        if (val == null) return undefined;
        return val;
    });
    return JSON.parse(str);
}

Then you can have a "normalized" JSON object by calling:

var obj = removeNulls(obj);
Matteo Piazza
  • 2,462
  • 7
  • 29
  • 38
0
echo json_encode(array_filter((array) $object, function($val) {
    return !empty($val);
}));
Octavian
  • 155
  • 8
  • 2
    Look at the accepted answer: _array_filter without second argument removes null elements of entry array_. So, that is much simpler than your proposal. – Adrian W May 25 '18 at 15:59
0
class Foo implements JsonSerializable
{
    public $param1;
    public $param2;
    
    public function jsonSerialize()
    {
        return array_filter((array) $this, function ($var) {
            return !is_null($var);
        });
    }
}

public function testJsonSerialization()
{
    $expectedJson = '{"param1":true}';

    $foo = new Foo();
    $foo->param1 = true;
    $foo->param2 = null;

    $this->assertEquals(
        $expectedJson,
        json_encode($foo)
    );
}`

of course you can create Abstract class with custom jsonSerialize method and extend all your DTOs from this

Chyngyz Sagynov
  • 151
  • 2
  • 5
0

A version that works with multi-dimensional arrays.

$withoutNull = function($a) use (&$withoutNull) {
    return array_filter(
        array_map(
            fn($p) => is_array($p) ? $withoutNull($p) : $p, $a
        )
    );
};

Example:

$a = [
    "name" => "nathan",
    "data" => [
        "age" => 27,
        "something" => null
    ],
    "another" => null
];
$b = $withoutNull($a);
print_r($b);

Output:

Array
(
    [name] => nathan
    [data] => Array
        (
            [age] => 27
        )

)
Nathan F.
  • 3,250
  • 3
  • 35
  • 69