Skip to content

Commit b1fd4cc

Browse files
committed
JsonValueReplace
1 parent 3ea7087 commit b1fd4cc

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

Diff for: README.md

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ A PHP implementation for finding unordered diff between two `JSON` documents.
1414
* To keep original order of object sets (for example `swagger.json` [parameters](https://swagger.io/docs/specification/describing-parameters/) list).
1515
* To make and apply JSON Patches, specified in [RFC 6902](http://tools.ietf.org/html/rfc6902) from the IETF.
1616
* To retrieve and modify data by [JSON Pointer](http://tools.ietf.org/html/rfc6901).
17+
* To recursively replace by JSON value.
1718

1819
## Installation
1920

@@ -126,6 +127,11 @@ Gets value from data at path specified `JSON Pointer` string.
126127
#### `remove`
127128
Removes value from data at path specified by segments.
128129

130+
### `JsonValueReplace`
131+
132+
#### `process`
133+
Recursively replaces all nodes equal to `search` value with `replace` value.
134+
129135
## Example
130136

131137
```php

Diff for: src/JsonValueReplace.php

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff;
4+
5+
6+
class JsonValueReplace
7+
{
8+
private $search;
9+
private $replace;
10+
private $path = '';
11+
private $pathItems = array();
12+
13+
/**
14+
* JsonReplace constructor.
15+
* @param mixed $search
16+
* @param mixed $replace
17+
*/
18+
public function __construct($search, $replace)
19+
{
20+
$this->search = $search;
21+
$this->replace = $replace;
22+
}
23+
24+
/**
25+
* Recursively replaces all nodes equal to `search` value with `replace` value.
26+
* @param $data
27+
* @return mixed
28+
*/
29+
public function process($data)
30+
{
31+
if (!is_array($data) && !is_object($data)) {
32+
return $data === $this->search ? $this->replace : $data;
33+
}
34+
35+
$originalKeys = $data instanceof \stdClass ? get_object_vars($data) : $data;
36+
37+
$diff = new JsonDiff($data, $this->search, JsonDiff::STOP_ON_DIFF);
38+
if ($diff->getDiffCnt() === 0) {
39+
return $this->replace;
40+
}
41+
42+
$result = array();
43+
44+
foreach ($originalKeys as $key => $originalValue) {
45+
$path = $this->path;
46+
$pathItems = $this->pathItems;
47+
$actualKey = $key;
48+
$this->path .= '/' . JsonPointer::escapeSegment($actualKey);
49+
$this->pathItems[] = $actualKey;
50+
51+
$result[$key] = $this->process($originalValue);
52+
53+
$this->path = $path;
54+
$this->pathItems = $pathItems;
55+
}
56+
57+
return $data instanceof \stdClass ? (object)$result : $result;
58+
}
59+
}

Diff for: tests/src/ReplaceTest.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff\Tests;
4+
5+
6+
use Swaggest\JsonDiff\JsonValueReplace;
7+
8+
class ReplaceTest extends \PHPUnit_Framework_TestCase
9+
{
10+
public function testReplace()
11+
{
12+
$data = json_decode(<<<JSON
13+
{
14+
"data": [
15+
{"a":"b","c":"d"},
16+
{"c":"d", "a":"b"},
17+
{"c":"d"}
18+
],
19+
"o":{"a":"b","c":"d"}
20+
}
21+
JSON
22+
);
23+
$replace = new JsonValueReplace(
24+
json_decode('{"a":"b","c":"d"}'),
25+
json_decode('{"a":"b","c":"d","e":"f"}')
26+
);
27+
28+
$result = $replace->process($data);
29+
$expected = json_decode(<<<JSON
30+
{
31+
"data": [
32+
{"a":"b","c":"d","e":"f"},
33+
{"c":"d", "a":"b","e":"f"},
34+
{"c":"d"}
35+
],
36+
"o":{"a":"b","c":"d","e":"f"}
37+
}
38+
JSON
39+
);
40+
41+
$this->assertEquals($expected, $result);
42+
}
43+
44+
45+
public function testReplaceScalar()
46+
{
47+
$data = json_decode(<<<JSON
48+
{
49+
"data": [
50+
{"a":"b","c":"d"},
51+
{"c":"d", "a":"b"},
52+
{"c":"d"}
53+
],
54+
"o":{"a":"b","c":"d"}
55+
}
56+
JSON
57+
);
58+
$replace = new JsonValueReplace("b", "B");
59+
60+
$result = $replace->process($data);
61+
$expected = json_decode(<<<JSON
62+
{
63+
"data": [
64+
{"a":"B","c":"d"},
65+
{"c":"d", "a":"B"},
66+
{"c":"d"}
67+
],
68+
"o":{"a":"B","c":"d"}
69+
}
70+
JSON
71+
);
72+
73+
$this->assertEquals($expected, $result);
74+
}
75+
76+
}

0 commit comments

Comments
 (0)