Skip to content

Commit 58eb65a

Browse files
FinesseRick van der Staaij
authored andcommitted
Added a JSON decode filter (#58)
* 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
1 parent f2fe5f2 commit 58eb65a

4 files changed

Lines changed: 195 additions & 6 deletions

File tree

docs/filter-rules.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ filters, take a look at the callback filter-rule, or check out "Extending the Fi
88
* [bool](#bool)()
99
* [callback](#callback)($callable, $allowNotSet = false)
1010
* [cut](#cut)($start, $length = null)
11+
* [decodeJSON](#decodejson)($assoc = true, $depth = 512, $options = 0)
1112
* [defaults](#defaults)($defaultValue)
1213
* [each](#each)($callable)
1314
* [encode](#encode)($toEncodingFormat = null, $fromEncodingFormat = null)
1415
* [float](#float)()
1516
* [int](#int)()
1617
* [letters](#letters)()
1718
* [lower](#lower)()
18-
* [numberFormat](numberformat)($decimals, $decimalPoint, $thousandSeparator)
19+
* [numberFormat](#numberformat)($decimals, $decimalPoint, $thousandSeparator)
1920
* [numbers](#numbers)()
2021
* [prepend](#prepend)($prepend)
2122
* [regexReplace](#regexreplace)($searchRegex, $replace)
@@ -94,15 +95,34 @@ $result = $f->filter([]); // note that no year is set
9495

9596
## Cut
9697

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

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

107+
## DecodeJSON
108+
109+
If you need to decode a JSON code. The usage is same as the PHP
110+
[json_decode](http://php.net/manual/en/function.json-decode.php) function.
111+
112+
```php
113+
$f = new Filter;
114+
$f->value('data')->decodeJSON();
115+
$result = $f->filter(['data' => '{"name": "Jack", "account": 1000}']);
116+
// array(1) {["data"] => array(2) {["name"] => string(4) "Jack", ["account"] => int(1000)}}
117+
```
118+
119+
Notes:
120+
121+
* The filter decodes objects to associative arrays by default. Provide `false` as the first `decodeJSON` argument to get
122+
objects.
123+
* The filter result is `null` if an invalid JSON string is provided.
124+
* The filter doesn't change a value if it is not a string.
125+
106126
## Defaults
107127

108128
When there is no data present for a given value key, you can default to a given value.

src/FilterResource.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function alnum()
4848
* Results rule that returns the value appended with a given value
4949
*
5050
* @param string $append
51-
* @return Chain
51+
* @return $this
5252
*/
5353
public function append($append)
5454
{
@@ -82,13 +82,28 @@ public function callback(callable $callable, $allowNotSet = false)
8282
*
8383
* @param int $start
8484
* @param int|null $length
85-
* @return Chain
85+
* @return $this
8686
*/
8787
public function cut($start, $length = null)
8888
{
8989
return $this->addRule(new FilterRule\Cut($start, $length));
9090
}
9191

92+
/**
93+
* Returns rule that decodes JSON code of a given value
94+
*
95+
* @param bool $assoc When `true`, decoded objects will be converted into associative arrays (the default value is
96+
* set to `true` because both Filter and Validator can't deal with objects)
97+
* @param int $depth Decode recursion dept
98+
* @param int $options Bitmask of JSON decode options
99+
* @see http://php.net/manual/en/function.json-decode.php More information about the parameters
100+
* @return $this
101+
*/
102+
public function decodeJSON($assoc = true, $depth = 512, $options = 0)
103+
{
104+
return $this->addRule(new FilterRule\DecodeJSON($assoc, $depth, $options));
105+
}
106+
92107
/**
93108
* Returns rule that defaults a given value if the data key was not provided
94109
*
@@ -190,7 +205,7 @@ public function numbers()
190205
* Results rule that returns the value prepended with a given value
191206
*
192207
* @param string $prepend
193-
* @return Chain
208+
* @return $this
194209
*/
195210
public function prepend($prepend)
196211
{

src/FilterRule/DecodeJSON.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Particle.
4+
*
5+
* @link http://github.com/particle-php for the canonical source repository
6+
* @copyright Copyright (c) 2005-2016 Particle (http://particle-php.com)
7+
* @license https://github.com/particle-php/Filter/blob/master/LICENSE New BSD License
8+
*/
9+
namespace Particle\Filter\FilterRule;
10+
11+
use Particle\Filter\FilterRule;
12+
13+
/**
14+
* Class DecodeJSON
15+
*
16+
* 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
17+
* a correct JSON or if an encoded data is deeper than the recursion limit, `null` is returned.
18+
*
19+
* @package Particle\Filter\FilterRule
20+
*/
21+
class DecodeJSON extends FilterRule
22+
{
23+
/**
24+
* @var bool When `true`, decoded objects will be converted into associative arrays
25+
*/
26+
protected $assoc;
27+
28+
/**
29+
* @var int Decode recursion depth
30+
*/
31+
protected $depth;
32+
33+
/**
34+
* @var int Bitmask of JSON decode options
35+
*/
36+
protected $options;
37+
38+
/**
39+
* Set required params for JSON decoding
40+
*
41+
* @param bool $assoc When `true`, decoded objects will be converted into associative arrays
42+
* @param int $depth Decode recursion dept
43+
* @param int $options Bitmask of JSON decode options
44+
* @see http://php.net/manual/en/function.json-decode.php More information about the parameters
45+
*/
46+
public function __construct($assoc, $depth, $options)
47+
{
48+
$this->assoc = $assoc;
49+
$this->depth = $depth;
50+
$this->options = $options;
51+
}
52+
53+
/**
54+
* Decodes the value JSON
55+
*
56+
* @param mixed $value
57+
* @return mixed
58+
*/
59+
public function filter($value)
60+
{
61+
if (!is_string($value)) {
62+
return $value;
63+
}
64+
65+
return json_decode($value, $this->assoc, $this->depth, $this->options);
66+
}
67+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
namespace Particle\Filter\Tests\FilterRule;
3+
4+
use Particle\Filter\Filter;
5+
6+
class DecodeJSONTest extends \PHPUnit_Framework_TestCase
7+
{
8+
/**
9+
* @var Filter
10+
*/
11+
protected $filter;
12+
13+
/**
14+
* Prepare the filter
15+
*/
16+
public function setUp()
17+
{
18+
$this->filter = new Filter();
19+
}
20+
21+
/**
22+
* @dataProvider getTestParams
23+
* @param mixed $value
24+
* @param bool $assoc
25+
* @param int $depth
26+
* @param int $options
27+
* @param mixed $filteredValue
28+
*/
29+
public function testDecodeJSONFilterRule($value, $assoc, $depth, $options, $filteredValue)
30+
{
31+
$this->filter->value('test')->decodeJSON($assoc, $depth, $options);
32+
33+
$result = $this->filter->filter([
34+
'test' => $value
35+
]);
36+
37+
$this->assertEquals($filteredValue, $result['test']);
38+
}
39+
40+
public function testDecodeJSONFilterRuleWithBigInt()
41+
{
42+
$this->filter->value('test1')->decodeJSON(false, 100, 0);
43+
$this->filter->value('test2')->decodeJSON(false, 100, JSON_BIGINT_AS_STRING);
44+
45+
$result = $this->filter->filter([
46+
'test1' => '1000000000000000000000000000000',
47+
'test2' => '1000000000000000000000000000000'
48+
]);
49+
50+
$this->assertInternalType('float', $result['test1']);
51+
$this->assertInternalType('string', $result['test2']);
52+
}
53+
54+
/**
55+
* @return array
56+
*/
57+
public function getTestParams()
58+
{
59+
return [
60+
// Ordinary JSON
61+
[
62+
'{"string": "foo", "int": 100500, "array": [false, true, null]}',
63+
false,
64+
100,
65+
0,
66+
(object)['string' => 'foo', 'int' => 100500, 'array' => [false, true, null]]
67+
],
68+
['"Hello"', false, 100, 0, 'Hello'],
69+
['1999', false, 100, 0, 1999],
70+
71+
// Using the assoc parameter
72+
['{"string": "foo", "int": 100500}', true, 100, 0, ['string' => 'foo', 'int' => 100500]],
73+
74+
// Using the depth parameter
75+
['{"1": {"2": {"3": {"4": "the end"}}}}', true, 100, 0, [1 => [2 => [3 => [4 => "the end"]]]]],
76+
['{"1": {"2": {"3": {"4": "the end"}}}}', true, 3, 0, null],
77+
78+
// Incorrect JSON
79+
['I am not a JSON', false, 100, 0, null],
80+
['', false, 100, 0, null],
81+
82+
// Not a string
83+
[null, false, 100, 0, null],
84+
[3456, false, 100, 0, 3456],
85+
];
86+
}
87+
}

0 commit comments

Comments
 (0)