Skip to content

Commit

Permalink
Added a JSON decode filter (#58)
Browse files Browse the repository at this point in the history
* Added the DecodeJSON filter

* Added a test for the filter

* Added the documentation for the filter

* Fixed the documentation

* The filter `$assoc` argument default value is set to `true`

* More notes to the documentation

* Added a note about why the `$accos` default value is set to true not to forget
  • Loading branch information
Finesse authored and Rick van der Staaij committed Dec 13, 2017
1 parent f2fe5f2 commit 58eb65a
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 6 deletions.
26 changes: 23 additions & 3 deletions docs/filter-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ filters, take a look at the callback filter-rule, or check out "Extending the Fi
* [bool](#bool)()
* [callback](#callback)($callable, $allowNotSet = false)
* [cut](#cut)($start, $length = null)
* [decodeJSON](#decodejson)($assoc = true, $depth = 512, $options = 0)
* [defaults](#defaults)($defaultValue)
* [each](#each)($callable)
* [encode](#encode)($toEncodingFormat = null, $fromEncodingFormat = null)
* [float](#float)()
* [int](#int)()
* [letters](#letters)()
* [lower](#lower)()
* [numberFormat](numberformat)($decimals, $decimalPoint, $thousandSeparator)
* [numberFormat](#numberformat)($decimals, $decimalPoint, $thousandSeparator)
* [numbers](#numbers)()
* [prepend](#prepend)($prepend)
* [regexReplace](#regexreplace)($searchRegex, $replace)
Expand Down Expand Up @@ -94,15 +95,34 @@ $result = $f->filter([]); // note that no year is set

## Cut

If you need to cut a string. Same usage as PHP substr.
If you need to cut a string. Same usage as PHP [substr](http://php.net/manual/en/function.substr.php).

```php
$f = new Filter;
$f->value('slug')->cut(0, 28);
$result = $f->filter(['slug' => 'my-very-super-extra-long-url-that-needs-to-be-cut]);
$result = $f->filter(['slug' => 'my-very-super-extra-long-url-that-needs-to-be-cut']);
// array(1) { ["slug"]=> string(28) "my-very-super-extra-long-url" }
```

## DecodeJSON

If you need to decode a JSON code. The usage is same as the PHP
[json_decode](http://php.net/manual/en/function.json-decode.php) function.

```php
$f = new Filter;
$f->value('data')->decodeJSON();
$result = $f->filter(['data' => '{"name": "Jack", "account": 1000}']);
// array(1) {["data"] => array(2) {["name"] => string(4) "Jack", ["account"] => int(1000)}}
```

Notes:

* The filter decodes objects to associative arrays by default. Provide `false` as the first `decodeJSON` argument to get
objects.
* The filter result is `null` if an invalid JSON string is provided.
* The filter doesn't change a value if it is not a string.

## Defaults

When there is no data present for a given value key, you can default to a given value.
Expand Down
21 changes: 18 additions & 3 deletions src/FilterResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function alnum()
* Results rule that returns the value appended with a given value
*
* @param string $append
* @return Chain
* @return $this
*/
public function append($append)
{
Expand Down Expand Up @@ -82,13 +82,28 @@ public function callback(callable $callable, $allowNotSet = false)
*
* @param int $start
* @param int|null $length
* @return Chain
* @return $this
*/
public function cut($start, $length = null)
{
return $this->addRule(new FilterRule\Cut($start, $length));
}

/**
* Returns rule that decodes JSON code of a given value
*
* @param bool $assoc When `true`, decoded objects will be converted into associative arrays (the default value is
* set to `true` because both Filter and Validator can't deal with objects)
* @param int $depth Decode recursion dept
* @param int $options Bitmask of JSON decode options
* @see http://php.net/manual/en/function.json-decode.php More information about the parameters
* @return $this
*/
public function decodeJSON($assoc = true, $depth = 512, $options = 0)
{
return $this->addRule(new FilterRule\DecodeJSON($assoc, $depth, $options));
}

/**
* Returns rule that defaults a given value if the data key was not provided
*
Expand Down Expand Up @@ -190,7 +205,7 @@ public function numbers()
* Results rule that returns the value prepended with a given value
*
* @param string $prepend
* @return Chain
* @return $this
*/
public function prepend($prepend)
{
Expand Down
67 changes: 67 additions & 0 deletions src/FilterRule/DecodeJSON.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* Particle.
*
* @link http://github.com/particle-php for the canonical source repository
* @copyright Copyright (c) 2005-2016 Particle (http://particle-php.com)
* @license https://github.com/particle-php/Filter/blob/master/LICENSE New BSD License
*/
namespace Particle\Filter\FilterRule;

use Particle\Filter\FilterRule;

/**
* Class DecodeJSON
*
* A filter that decodes the given value from JSON. If a value is not a string, it is returned as is. If a value is not
* a correct JSON or if an encoded data is deeper than the recursion limit, `null` is returned.
*
* @package Particle\Filter\FilterRule
*/
class DecodeJSON extends FilterRule
{
/**
* @var bool When `true`, decoded objects will be converted into associative arrays
*/
protected $assoc;

/**
* @var int Decode recursion depth
*/
protected $depth;

/**
* @var int Bitmask of JSON decode options
*/
protected $options;

/**
* Set required params for JSON decoding
*
* @param bool $assoc When `true`, decoded objects will be converted into associative arrays
* @param int $depth Decode recursion dept
* @param int $options Bitmask of JSON decode options
* @see http://php.net/manual/en/function.json-decode.php More information about the parameters
*/
public function __construct($assoc, $depth, $options)
{
$this->assoc = $assoc;
$this->depth = $depth;
$this->options = $options;
}

/**
* Decodes the value JSON
*
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (!is_string($value)) {
return $value;
}

return json_decode($value, $this->assoc, $this->depth, $this->options);
}
}
87 changes: 87 additions & 0 deletions tests/FilterRule/DecodeJSONTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php
namespace Particle\Filter\Tests\FilterRule;

use Particle\Filter\Filter;

class DecodeJSONTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Filter
*/
protected $filter;

/**
* Prepare the filter
*/
public function setUp()
{
$this->filter = new Filter();
}

/**
* @dataProvider getTestParams
* @param mixed $value
* @param bool $assoc
* @param int $depth
* @param int $options
* @param mixed $filteredValue
*/
public function testDecodeJSONFilterRule($value, $assoc, $depth, $options, $filteredValue)
{
$this->filter->value('test')->decodeJSON($assoc, $depth, $options);

$result = $this->filter->filter([
'test' => $value
]);

$this->assertEquals($filteredValue, $result['test']);
}

public function testDecodeJSONFilterRuleWithBigInt()
{
$this->filter->value('test1')->decodeJSON(false, 100, 0);
$this->filter->value('test2')->decodeJSON(false, 100, JSON_BIGINT_AS_STRING);

$result = $this->filter->filter([
'test1' => '1000000000000000000000000000000',
'test2' => '1000000000000000000000000000000'
]);

$this->assertInternalType('float', $result['test1']);
$this->assertInternalType('string', $result['test2']);
}

/**
* @return array
*/
public function getTestParams()
{
return [
// Ordinary JSON
[
'{"string": "foo", "int": 100500, "array": [false, true, null]}',
false,
100,
0,
(object)['string' => 'foo', 'int' => 100500, 'array' => [false, true, null]]
],
['"Hello"', false, 100, 0, 'Hello'],
['1999', false, 100, 0, 1999],

// Using the assoc parameter
['{"string": "foo", "int": 100500}', true, 100, 0, ['string' => 'foo', 'int' => 100500]],

// Using the depth parameter
['{"1": {"2": {"3": {"4": "the end"}}}}', true, 100, 0, [1 => [2 => [3 => [4 => "the end"]]]]],
['{"1": {"2": {"3": {"4": "the end"}}}}', true, 3, 0, null],

// Incorrect JSON
['I am not a JSON', false, 100, 0, null],
['', false, 100, 0, null],

// Not a string
[null, false, 100, 0, null],
[3456, false, 100, 0, 3456],
];
}
}

0 comments on commit 58eb65a

Please sign in to comment.