Skip to content

Commit bb3e3b4

Browse files
authored
Fix and improve rearrange (#44)
1 parent d223be0 commit bb3e3b4

File tree

7 files changed

+1376
-18
lines changed

7 files changed

+1376
-18
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [3.8.3] - 2021-09-25
8+
9+
### Fixed
10+
- Redundant operations in array patches that strip first element.
11+
- XOR hash collision for properties having equal parts.
12+
13+
### Added
14+
- Rearrange indexing by non-scalar properties that contain object, using XOR hash.
15+
716
## [3.8.2] - 2021-09-17
817

918
### Fixed
@@ -60,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6069
### Added
6170
- Compatibility option to `TOLERATE_ASSOCIATIVE_ARRAYS` that mimic JSON objects.
6271

72+
[3.8.3]: https://github.com/swaggest/json-diff/compare/v3.8.2...v3.8.3
6373
[3.8.2]: https://github.com/swaggest/json-diff/compare/v3.8.1...v3.8.2
6474
[3.8.1]: https://github.com/swaggest/json-diff/compare/v3.8.0...v3.8.1
6575
[3.8.0]: https://github.com/swaggest/json-diff/compare/v3.7.5...v3.8.0

src/JsonDiff.php

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ class JsonDiff
7979
private $jsonPatch;
8080

8181
/** @var JsonHash */
82-
private $jsonHashOriginal;
83-
84-
/** @var JsonHash */
85-
private $jsonHashNew;
82+
private $jsonHash;
8683

8784
/**
8885
* @param mixed $original
@@ -410,7 +407,7 @@ private function rearrangeArray(array $original, array $new)
410407
/** @var mixed[string] $f */
411408
$f = get_object_vars($first);
412409
foreach ($f as $key => $value) {
413-
if (is_array($value) || $value instanceof \stdClass) {
410+
if (is_array($value)) {
414411
continue;
415412
}
416413

@@ -425,11 +422,19 @@ private function rearrangeArray(array $original, array $new)
425422
break;
426423
}
427424
$value = $item->$key;
428-
if ($value instanceof \stdClass || is_array($value)) {
425+
if (is_array($value)) {
429426
$keyIsUnique = false;
430427
break;
431428
}
432429

430+
if ($value instanceof \stdClass) {
431+
if ($this->jsonHash === null) {
432+
$this->jsonHash = new JsonHash($this->options);
433+
}
434+
435+
$value = $this->jsonHash->xorHash($value);
436+
}
437+
433438
if (isset($uniqueIdx[$value])) {
434439
$keyIsUnique = false;
435440
break;
@@ -461,10 +466,18 @@ private function rearrangeArray(array $original, array $new)
461466

462467
$value = $item->$uniqueKey;
463468

464-
if ($value instanceof \stdClass || is_array($value)) {
469+
if (is_array($value)) {
465470
return $new;
466471
}
467472

473+
if ($value instanceof \stdClass) {
474+
if ($this->jsonHash === null) {
475+
$this->jsonHash = new JsonHash($this->options);
476+
}
477+
478+
$value = $this->jsonHash->xorHash($value);
479+
}
480+
468481

469482
if (isset($uniqueIdx[$value])) {
470483
$idx = $uniqueIdx[$value];
@@ -490,26 +503,24 @@ private function rearrangeArray(array $original, array $new)
490503
}
491504

492505
ksort($newRearranged);
493-
$newRearranged = array_values($newRearranged);
494506
return $newRearranged;
495507
}
496508

497509
private function rearrangeEqualItems(array $original, array $new)
498510
{
499-
if ($this->jsonHashOriginal === null) {
500-
$this->jsonHashOriginal = new JsonHash($this->options);
501-
$this->jsonHashNew = new JsonHash($this->options);
511+
if ($this->jsonHash === null) {
512+
$this->jsonHash = new JsonHash($this->options);
502513
}
503514

504515
$origIdx = [];
505516
foreach ($original as $i => $item) {
506-
$hash = $this->jsonHashOriginal->xorHash($item);
517+
$hash = $this->jsonHash->xorHash($item);
507518
$origIdx[$hash][] = $i;
508519
}
509520

510521
$newIdx = [];
511522
foreach ($new as $i => $item) {
512-
$hash = $this->jsonHashNew->xorHash($item);
523+
$hash = $this->jsonHash->xorHash($item);
513524
$newIdx[$i] = $hash;
514525
}
515526

@@ -535,7 +546,6 @@ private function rearrangeEqualItems(array $original, array $new)
535546
}
536547

537548
ksort($newRearranged);
538-
$newRearranged = array_values($newRearranged);
539549

540550
return $newRearranged;
541551
}

src/JsonHash.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function xorHash($data, $path = '')
6464
foreach ($dataKeys as $key => $value) {
6565
$propertyPath = $path . '/' .
6666
JsonPointer::escapeSegment($key, (bool)($this->options & JsonDiff::JSON_URI_FRAGMENT_ID));
67-
$propertyHash = $propertyPath . $this->xorHash($value, $propertyPath);
67+
$propertyHash = $propertyPath . md5($key, true) . $this->xorHash($value, $propertyPath);
6868
if (strlen($xorHash) < strlen($propertyHash)) {
6969
$xorHash = str_pad($xorHash, strlen($propertyHash));
7070
}

0 commit comments

Comments
 (0)