PHP how to json_encode() return from rrd_xport()?

384 Views Asked by At

I've recently run into an issue doing json_encode(rrd_xport($options)); on RRD files generated by Nagios/Nagiosgraph.

json_encode() appears to fall over (thus returning FALSE) when rrd_xport() returns NaN as element values. For example (given $var = rrd_xport()'s return):

print_r($var) output:

Array
(
    [1418265300] =     297
    [1418265600] =     296.79333333333
    [1418265900] =     296.8
    [1418266200] =     295.79333333333
    [1418266500] =     295.40666666667
    [1418266800] =     296
    [1418267100] =     296
    [1418267400] =     296
    [1418267700] =     295.6
    [1418268000] =     296
    [1418268300] =     296.00666666667
    [1418268600] =     296.39333333333
    [1418268900] =     295.59333333333
    [1418269200] =     295.4
    [1418269500] =     295.79333333333
)

json_encode($var) output:

{"1418263800":297,"1418264100":297.40666666667,"1418264400":297.39333333333,"1418264700":297,"1418265000":297,"1418265300":297,"1418265600":296.79333333333,"1418265900":296.8,"1418266200":295.79333333333,"1418266500":295.40666666667,"1418266800":296,"1418267100":296,"1418267400":296,"1418267700":295.6,"1418268000":296,"1418268300":296.00666666667,"1418268600":296.39333333333,"1418268900":295.59333333333,"1418269200":295.4,"1418269500":295.79333333333}

Now, when we (rrd_xport) introduce a NaN to an element value, we see json_encode() spew:

NEW print_r($var) output:

Array
(
    [1418265300] =     297
    [1418265600] =     296.79333333333
    [1418265900] =     296.8
    [1418266200] =     295.79333333333
    [1418266500] =     295.40666666667
    [1418266800] =     296
    [1418267100] =     296
    [1418267400] =     296
    [1418267700] =     295.6
    [1418268000] =     296
    [1418268300] =     296.00666666667
    [1418268600] =     296.39333333333
    [1418268900] =     295.59333333333
    [1418269200] =     295.4
    [1418269500] =     295.79333333333
    [1418269800] =     NAN
)

var_dump(json_encode($var)) output:

bool(false)

Finally, my question: What's the nicest way to deal with this - do we need to trawl the entire array and replace NaN? (The real output is far bigger than this example, and multidimensional) Surely there's a better way!

2

There are 2 best solutions below

0
On BEST ANSWER

JSON Specification has not anything about how to encode NaN or Inf entities:

Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.

You should iterate through and replace is_nan($v) values to anything applicable with JSON, for example to null...

Or you can implement your own js_encode function

0
On

Wound up looping through the array, thanks vp_arth!

function killnan($maybeHasNan)
{
        if (gettype($maybeHasNan) != "array")
        {
                echo "AHSHIT\n";
                return;
        }

        $iMakedThis = Array();

        foreach ($maybeHasNan as $key =     $value)
        {
                if (gettype($value) == "array")
                {
                        # go deeper neo
                        $iMakedThis[$key] = killnan($value);
                }

                elseif (gettype($value) == "double" && is_nan($value))
                {
                        $iMakedThis[$key] = NULL;
                }

                else
                {
                        $iMakedThis[$key] = $value;
                }
        }

        return $iMakedThis;
}