{"id":25081264,"url":"https://github.com/lukascivil/treewalker","last_synced_at":"2026-04-25T09:07:42.054Z","repository":{"id":60774579,"uuid":"50965225","full_name":"lukascivil/TreeWalker","owner":"lukascivil","description":"PHP JSON diff","archived":false,"fork":false,"pushed_at":"2022-08-16T16:35:02.000Z","size":59,"stargazers_count":72,"open_issues_count":0,"forks_count":30,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-30T15:08:04.274Z","etag":null,"topics":["diff","json","merge","php"],"latest_commit_sha":null,"homepage":"http://treewalker.lukascivil.com.br/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukascivil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-03T01:35:17.000Z","updated_at":"2025-01-25T04:09:38.000Z","dependencies_parsed_at":"2022-10-04T15:40:17.244Z","dependency_job_id":null,"html_url":"https://github.com/lukascivil/TreeWalker","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukascivil%2FTreeWalker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukascivil%2FTreeWalker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukascivil%2FTreeWalker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukascivil%2FTreeWalker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukascivil","download_url":"https://codeload.github.com/lukascivil/TreeWalker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509236,"owners_count":20950232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diff","json","merge","php"],"created_at":"2025-02-07T04:38:00.456Z","updated_at":"2026-04-25T09:07:42.047Z","avatar_url":"https://github.com/lukascivil.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TreeWalker\n\nA simple and lightweight PHP library for manipulating nested structures — arrays, objects and JSON strings interchangeably.\n\n[![Build Status](https://github.com/lukascivil/TreeWalker/workflows/PHP%20Composer/badge.svg)]()\n[![Total Downloads](https://poser.pugx.org/lukascivil/treewalker/downloads)](https://packagist.org/packages/lukascivil/treewalker)\n[![codecov](https://codecov.io/gh/lukascivil/TreeWalker/branch/master/graph/badge.svg)](https://codecov.io/gh/lukascivil/TreeWalker)\n[![License](https://poser.pugx.org/lukascivil/treewalker/license.svg)](https://packagist.org/packages/lukascivil/treewalker)\n\n## Methods\n\n| Method | Description |\n|--------|-------------|\n| `getdiff()` | Returns the difference between two structures |\n| `walker()` | Walks recursively through a structure, allowing edits and deletions |\n| `structMerge()` | Merges two structures (first argument takes precedence) |\n| `createDynamicallyObjects()` | Creates nested keys dynamically |\n| `getDynamicallyValue()` | Reads a value by dynamic key path |\n| `setDynamicallyValue()` | Sets a value by dynamic key path |\n\n### [Live example](http://treewalker.lukascivil.com.br/)\n\nAll methods accept and return any of the three supported structure types:\n\n```\n\"jsonstring\" | \"object\" | \"array\"\n```\n\n## Requirements\n\n- PHP \u003e= 8.1\n\n## Installation\n\n```bash\ncomposer require lukascivil/treewalker\n```\n\n## Usage\n\n### Initialization\n\n```php\n\u003c?php\n\n$treeWalker = new TreeWalker([\n    \"debug\"      =\u003e false,    // true = append execution time to output\n    \"returntype\" =\u003e \"array\"   // \"jsonstring\" | \"object\" | \"array\"\n]);\n```\n\n---\n\n### getdiff()\n\nReturns the difference between two structures, split into `new`, `removed` and `edited` keys.\n\n```php\n\u003c?php\n\n$struct1 = [\"casa\" =\u003e 1, \"b\" =\u003e \"5\", \"cafeina\" =\u003e [\"ss\" =\u003e \"ddd\"], \"oi\" =\u003e 5];\n$struct2 = [\"casa\" =\u003e 2, \"cafeina\" =\u003e [\"ss\" =\u003e \"dddd\"], \"oi2\" =\u003e 5];\n\n$treeWalker-\u003egetdiff($struct1, $struct2, false); // false = flat slash-delimited keys\n```\n\nOutput:\n\n```json\n{\n    \"new\": {\n        \"b\": \"5\",\n        \"oi\": 5\n    },\n    \"removed\": {\n        \"oi2\": 5\n    },\n    \"edited\": {\n        \"casa\": {\n            \"oldvalue\": 2,\n            \"newvalue\": 1\n        },\n        \"cafeina/ss\": {\n            \"oldvalue\": \"dddd\",\n            \"newvalue\": \"ddd\"\n        }\n    }\n}\n```\n\nPass `true` as the third argument to get nested output instead of slash-delimited keys:\n\n```php\n\u003c?php\n\n$treeWalker-\u003egetdiff($struct1, $struct2, true); // true = nested output\n```\n\n---\n\n### walker()\n\nWalks recursively through the structure. The callback receives the parent array, the current key and the current value by reference, allowing in-place modification or deletion.\n\n```php\n\u003c?php\n\n$struct = [\"casa\" =\u003e 2, \"cafeina\" =\u003e [\"ss\" =\u003e [\"ff\" =\u003e 21, \"ff1\" =\u003e 22]], \"oi2\" =\u003e 5];\n\n$treeWalker-\u003ewalker($struct, function (\u0026$struct, $key, \u0026$value) {\n    if ($key === \"ff\") {\n        unset($struct[$key]);      // delete node\n    }\n\n    if ($key === \"ff1\") {\n        $value = [\"son\" =\u003e \"tiago\"]; // replace value\n    }\n});\n```\n\nOutput:\n\n```json\n{\"casa\": 2, \"cafeina\": {\"ss\": {\"ff1\": {\"son\": \"tiago\"}}}, \"oi2\": 5}\n```\n\n---\n\n### structMerge()\n\nMerges two structures. Values from the first argument take precedence over the second.\n\n```php\n\u003c?php\n\n$struct1 = [\"casa\" =\u003e 1, \"b\" =\u003e \"5\", \"cafeina\" =\u003e [\"ss1\" =\u003e \"1\", \"ss2\" =\u003e \"2\"], \"oi\" =\u003e 5];\n$struct2 = [\"casa\" =\u003e 2, \"cafeina\" =\u003e [\"ss\" =\u003e [\"ff\" =\u003e 21, \"ff1\" =\u003e 22]], \"oi2\" =\u003e 5, \"ss\" =\u003e \"dddddf\"];\n\n$treeWalker-\u003estructMerge($struct1, $struct2, true); // true = nested output\n```\n\nOutput:\n\n```json\n{\"casa\": 1, \"b\": \"5\", \"cafeina\": {\"ss1\": \"1\", \"ss2\": \"2\", \"ss\": {\"ff\": 21, \"ff1\": 22}}, \"oi\": 5, \"oi2\": 5, \"ss\": \"dddddf\"}\n```\n\n---\n\n### createDynamicallyObjects()\n\nCreates nested empty objects from a dynamic array of keys.\n\n```php\n\u003c?php\n\n$struct = [\"casa\" =\u003e 1, \"b\" =\u003e \"5\", \"cafeina\" =\u003e [\"ss\" =\u003e \"ddd\"], \"oi\" =\u003e 5];\n\n$treeWalker-\u003ecreateDynamicallyObjects($struct, [1, 2, 5, 9, 10, 11]);\n```\n\nOutput:\n\n```json\n{\n    \"casa\": 1,\n    \"b\": \"5\",\n    \"cafeina\": {\"ss\": \"ddd\"},\n    \"oi\": 5,\n    \"1\": {\n        \"2\": {\n            \"5\": {\n                \"9\": {\n                    \"10\": {\n                        \"11\": {}\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n---\n\n### getDynamicallyValue()\n\nReads a value from a structure using a dynamic key path.\n\n```php\n\u003c?php\n\n$struct = [\"casa\" =\u003e 2, \"cafeina\" =\u003e [\"ss\" =\u003e [\"ff\" =\u003e 21, \"ff1\" =\u003e 22]], \"oi2\" =\u003e 5];\n\n// Static access\n$struct[\"cafeina\"][\"ss\"];\n\n// Dynamic access\n$treeWalker-\u003egetDynamicallyValue($struct, [\"cafeina\", \"ss\"]);\n```\n\nOutput:\n\n```json\n{\"ff\": 21, \"ff1\": 22}\n```\n\n---\n\n### setDynamicallyValue()\n\nSets a value in a structure using a dynamic key path.\n\n```php\n\u003c?php\n\n$struct = [\"casa\" =\u003e 2, \"cafeina\" =\u003e [\"ss\" =\u003e [\"ff\" =\u003e 21, \"ff1\" =\u003e 22]], \"oi2\" =\u003e 5];\n\n// Static access\n$struct[\"cafeina\"][\"ss\"] = \"newvalue\";\n\n// Dynamic access\n$treeWalker-\u003esetDynamicallyValue($struct, [\"cafeina\", \"ss\"], \"newvalue\");\n```\n\nOutput:\n\n```json\n{\"casa\": 2, \"cafeina\": {\"ss\": \"newvalue\"}, \"oi2\": 5}\n```\n\n---\n\n## Development\n\n```bash\ncomposer install       # install dev dependencies\ncomposer test          # run tests with coverage\ncomposer check-format  # PSR-2 lint\ncomposer format        # PSR-2 autofix\n```\n\n## Additional context\n\nIf you need the JavaScript equivalent for client-side structure comparison, see [JsonDifference](https://github.com/lukascivil/jsondiffer).\n\n## License\n\nMIT © [Lucas Cordeiro da Silva](https://github.com/lukascivil)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukascivil%2Ftreewalker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukascivil%2Ftreewalker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukascivil%2Ftreewalker/lists"}