Skip to content

Commit d4c8752

Browse files
authored
Merge pull request #2 from adhocore/develop
Develop
2 parents e18fa7d + a84973b commit d4c8752

File tree

3 files changed

+89
-40
lines changed

3 files changed

+89
-40
lines changed

readme.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,40 @@ $fixer->fix('...');
3939

4040
## Error
4141

42-
If there's error and fixer cant fix the JSON for some reason, it will throw a `RunttimeException`.
42+
If there's error and fixer cant fix the JSON for some reason, it will throw a `RuntimeException`.
4343
You can disable this behavior by passing silent flag (2nd param) to `fix()` in which case original input is returned:
4444

4545
```php
46-
(new Fixer)->fix('invalid', true);
46+
(new Fixer)->silent()->fix('invalid');
4747
// 'invalid'
48+
49+
(new Fixer)->silent(true)->fix('invalid');
50+
// 'invalid'
51+
52+
(new Fixer)->silent(false)->fix('invalid');
53+
// RuntimeException
4854
```
4955

5056
## Missing Value
5157

52-
By default missing values are padded with `null`. You can change it by passing 3rd param to `fix()`:
58+
By default missing values are padded with `null`. You can change it passing desired value to `missingValue()`:
5359

5460
```php
5561
// key b is missing value and is padded with `null`
5662
$json = (new Fixer)->fix('{"a":1,"b":');
5763
// {"a":1,"b":null}
5864

5965
// key b is missing value and is padded with `true`
60-
$json = (new Fixer)->fix('{"a":1,"b":', false, 'true');
66+
$json = (new Fixer)->missingValue(true)->fix('{"a":1,"b":');
6167
// {"a":1,"b":true}
6268

6369
// key b is missing value and is padded with `"truncated"`
6470
// Note that you can actually inject a whole new JSON subset as 3rd param
6571
// but that should be a valid JSON segment and is not checked by fixer.
66-
$json = (new Fixer)->fix('{"a":1,"b":', false, '"truncated"');
72+
$json = (new Fixer)->missingValue('"truncated"')->fix('{"a":1,"b":');
6773
// {"a":1,"b":"truncated"}
6874
```
75+
76+
## Todo
77+
78+
- [ ] Configurable missing value as per context (options)

src/Fixer.php

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class Fixer
2020
/** @var bool If current char is within a string */
2121
protected $inStr = false;
2222

23+
/** @var bool Whether to throw Exception on failure */
24+
protected $silent = false;
25+
2326
/** @var array The complementary pairs */
2427
protected $pairs = [
2528
'{' => '}',
@@ -36,18 +39,50 @@ class Fixer
3639
/** @var string Missing value. (Options: true, false, null) */
3740
protected $missingValue = 'null';
3841

42+
/**
43+
* Set/unset silent mode.
44+
*
45+
* @param bool $silent
46+
*
47+
* @return $this
48+
*/
49+
public function silent($silent = true)
50+
{
51+
$this->silent = (bool) $silent;
52+
53+
return $this;
54+
}
55+
56+
/**
57+
* Set missing value.
58+
*
59+
* @param mixed $value
60+
*
61+
* @return $this
62+
*/
63+
public function missingValue($value)
64+
{
65+
if ($value === null) {
66+
$value = 'null';
67+
} elseif (\is_bool($value)) {
68+
$value = $value ? 'true' : 'false';
69+
}
70+
71+
$this->missingValue = $value;
72+
73+
return $this;
74+
}
75+
3976
/**
4077
* Fix the truncated JSON.
4178
*
42-
* @param string $json The JSON string to fix.
43-
* @param bool $silent If silent, doesnt throw when fixing fails.
44-
* @param string $missingValue Missing value constructor. (Options: true, false, null).
79+
* @param string $json The JSON string to fix.
4580
*
4681
* @throws \RuntimeExcaption When fixing fails.
4782
*
4883
* @return string Fixed JSON. If failed with silent then original JSON.
4984
*/
50-
public function fix($json, $silent = false, $missingValue = 'null')
85+
public function fix($json)
5186
{
5287
list($head, $json, $tail) = $this->trim($json);
5388

@@ -59,16 +94,17 @@ public function fix($json, $silent = false, $missingValue = 'null')
5994
return $tmpJson;
6095
}
6196

62-
$this->reset($missingValue);
97+
$this->reset();
6398

64-
return $head . $this->doFix(\rtrim($json), $silent) . $tail;
99+
return $head . $this->doFix($json) . $tail;
65100
}
66101

67102
protected function trim($json)
68103
{
69104
\preg_match('/^(\s*)([^\s]+)(\s*)$/', $json, $match);
70105

71-
$match += ['', '', \trim($json), ''];
106+
$match += ['', '', '', ''];
107+
$match[2] = \trim($json);
72108

73109
\array_shift($match);
74110

@@ -95,6 +131,14 @@ protected function quickFix($json)
95131
return $this->padString($json);
96132
}
97133

134+
protected function reset()
135+
{
136+
$this->stack = [];
137+
$this->inStr = false;
138+
$this->objectPos = -1;
139+
$this->arrayPos = -1;
140+
}
141+
98142
protected function maybeLiteral($json)
99143
{
100144
if (!\in_array($json[0], ['t', 'f', 'n'])) {
@@ -112,18 +156,7 @@ protected function maybeLiteral($json)
112156
// @codeCoverageIgnoreEnd
113157
}
114158

115-
protected function reset($missingValue = 'null')
116-
{
117-
$this->stack = [];
118-
$this->inStr = false;
119-
120-
$this->objectPos = -1;
121-
$this->arrayPos = -1;
122-
123-
$this->missingValue = $missingValue;
124-
}
125-
126-
protected function doFix($json, $silent = false)
159+
protected function doFix($json)
127160
{
128161
list($index, $char) = [-1, ''];
129162

@@ -137,7 +170,7 @@ protected function doFix($json, $silent = false)
137170
}
138171
}
139172

140-
return $this->fixOrFail($json, $silent);
173+
return $this->fixOrFail($json);
141174
}
142175

143176
protected function stack($prev, $char, $index, $next)
@@ -208,7 +241,7 @@ protected function updatePos($char, $index)
208241
}
209242
}
210243

211-
protected function fixOrFail($json, $silent)
244+
protected function fixOrFail($json)
212245
{
213246
$length = \strlen($json);
214247
$tmpJson = $this->pad($json);
@@ -217,7 +250,7 @@ protected function fixOrFail($json, $silent)
217250
return $tmpJson;
218251
}
219252

220-
if ($silent) {
253+
if ($this->silent) {
221254
return $json;
222255
}
223256

tests/FixerTest.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,45 @@
66

77
class FixerTest extends \PHPUnit\Framework\TestCase
88
{
9-
protected static $fixer;
9+
protected $fixer;
1010

11-
public static function setUpBeforeClass()
11+
public function setUp()
1212
{
13-
static::$fixer = new Fixer;
13+
$this->fixer = new Fixer;
1414
}
1515

1616
/** @dataProvider theTests */
1717
public function test($json, $expect, $msg = null)
1818
{
19-
$this->assertSame($expect, static::$fixer->fix($json), $msg);
19+
$this->assertSame($expect, $this->fixer->fix($json), $msg);
2020
}
2121

2222
public function test_invalid_literal()
2323
{
24-
$this->assertSame('{"a" : invalid', static::$fixer->fix('{"a" : invalid', true));
25-
$this->assertSame(' hmm ', static::$fixer->fix(' hmm ', true));
24+
$this->fixer->silent(true);
25+
26+
$this->assertSame('{"a" : invalid', $this->fixer->fix('{"a" : invalid'));
27+
$this->assertSame(' hmm ', $this->fixer->fix(' hmm '));
2628
}
2729

2830
public function test_ws()
2931
{
30-
$this->assertSame('{ "a" :null}', static::$fixer->fix('{ "a" :'));
31-
$this->assertSame("\n [{}]", static::$fixer->fix("\n [{,"));
32+
$this->assertSame('{ "a" :null}', $this->fixer->missingValue(null)->fix('{ "a" :'));
33+
$this->assertSame("\n [{}]", $this->fixer->fix("\n [{,"));
3234
}
3335

3436
public function test_custom_missing()
3537
{
36-
$this->assertSame('{"a":false}', static::$fixer->fix('{"a', false, 'false'));
37-
$this->assertSame('{"a":true}', static::$fixer->fix('{"a":', false, 'true'));
38-
$this->assertSame('{"a":1,"b":"missing"}', static::$fixer->fix('{"a":1,"b"', false, '"missing"'));
38+
$this->assertSame('{"a":false}', $this->fixer->missingValue(false)->fix('{"a'));
39+
$this->assertSame('{"a":true}', $this->fixer->missingValue('true')->fix('{"a":'));
40+
$this->assertSame('{"a":1,"b":"missing"}', $this->fixer->missingValue('"missing"')->fix('{"a":1,"b"'));
3941
}
4042

4143
public function test_fail_silent()
4244
{
43-
$this->assertSame('{"a"}', static::$fixer->fix('{"a"}', true));
45+
$this->fixer->silent(true);
46+
47+
$this->assertSame('{"a"}', $this->fixer->fix('{"a"}'));
4448
}
4549

4650
/**
@@ -49,7 +53,9 @@ public function test_fail_silent()
4953
*/
5054
public function test_fail_throws()
5155
{
52-
static::$fixer->fix('{,"a');
56+
$this->fixer->silent(false);
57+
58+
$this->fixer->fix('{,"a');
5359
}
5460

5561
public function theTests()

0 commit comments

Comments
 (0)