{"id":45137226,"url":"https://github.com/pwm/jgami","last_synced_at":"2026-02-20T00:06:15.437Z","repository":{"id":57046058,"uuid":"154472847","full_name":"pwm/jgami","owner":"pwm","description":"Have you ever mapped a function over a list? Now you can do the same with JSON!","archived":false,"fork":false,"pushed_at":"2018-10-26T19:55:51.000Z","size":52,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-21T01:11:12.848Z","etag":null,"topics":["json","mapping","tree"],"latest_commit_sha":null,"homepage":"","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/pwm.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-24T09:17:15.000Z","updated_at":"2022-09-07T08:29:36.000Z","dependencies_parsed_at":"2022-08-24T05:00:20.720Z","dependency_job_id":null,"html_url":"https://github.com/pwm/jgami","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/pwm/jgami","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwm%2Fjgami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwm%2Fjgami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwm%2Fjgami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwm%2Fjgami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwm","download_url":"https://codeload.github.com/pwm/jgami/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwm%2Fjgami/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["json","mapping","tree"],"created_at":"2026-02-20T00:06:13.181Z","updated_at":"2026-02-20T00:06:15.429Z","avatar_url":"https://github.com/pwm.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JGami\n\n[![Build Status](https://travis-ci.org/pwm/jgami.svg?branch=master)](https://travis-ci.org/pwm/jgami)\n[![codecov](https://codecov.io/gh/pwm/jgami/branch/master/graph/badge.svg)](https://codecov.io/gh/pwm/jgami)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/94f5bb5073dc902b547f/test_coverage)](https://codeclimate.com/github/pwm/jgami/test_coverage)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nHave you ever mapped a function over a list? Now you can do the same with JSON!\n\nJGami provides a simple API to update values in arbitrarily complex JSON structures while preserving structural integrity.\n\n## Table of Contents\n\n* [Requirements](#requirements)\n* [Installation](#installation)\n* [Usage](#usage)\n* [How it works](#how-it-works)\n* [Tests](#tests)\n* [Changelog](#changelog)\n* [Licence](#licence)\n\n## Requirements\n\nPHP 7.2+\n\n## Installation\n\n    $ composer require pwm/jgami\n\n## Usage\n\nIt's probably easiest to dive straight into some sample code. We will update some JSON data to our liking by mapping a function over it:\n\n```php\n// What we have\n$json = '{\n    \"name\": \"Alice\",\n    \"age\": 27,\n    \"likes\": [\n        \"Types\",\n        \"Graphs\",\n        \"Nature\"\n    ],\n    \"job\": {\n        \"title\": \"Developer\",\n        \"company\": \"Acme Corp.\"\n    },\n    \"pets\": [\n        {\n            \"name\": [\"Woof\"],\n            \"type\": \"Dog\"\n        },\n        {\n            \"name\": [\"Mr. Grumpy\", \"Mrs. Grumpy\"],\n            \"type\": \"Cat\"\n        }\n    ]\n}';\n\n// What we want\n$expectedJson = '{\n    \"name\": \"Alice Wonderland\",\n    \"age\": 37,\n    \"likes\": [\n        \"Types\",\n        \"Trees\",\n        \"Nature\"\n    ],\n    \"job\": {\n        \"title\": \"Developer\",\n        \"company\": \"Acme Corp.\"\n    },\n    \"pets\": [\n        {\n            \"name\": [\"Woof \u003c3\"],\n            \"type\": \"Dog\"\n        },\n        {\n            \"name\": [\"Mr. Grumpy \u003c3\", \"Mrs. Grumpy \u003c3\"],\n            \"type\": \"Cat\"\n        }\n    ]\n}';\n\n// Our update function, to be mapped over our JSON data\n// It takes a Node and return a JVal ie. a json value\n$f = function (Node $node): JVal {\n    $jVal = $node-\u003ejVal();\n    if ($jVal-\u003eval() === 'Graphs') {\n        // Replace \"Graphs\" with \"Trees\"\n        $jVal = new JString('Trees');\n    } elseif ($node-\u003ekey()-\u003eeq('age')) {\n        // Add 10 to values with key \"age\"\n        $jVal = new JInt($jVal-\u003eval() + 10);\n    } elseif ($node-\u003epath()-\u003ehasAll('pets', 'name')) {\n        // Add \" \u003c3\" to values in paths with \"pets\" and \"name\"\n        $jVal = new JString($jVal-\u003eval() . ' \u003c3');\n    } elseif ($node-\u003epath()-\u003ehasNone('pets') \u0026\u0026 $node-\u003ekey()-\u003eeq('name')) {\n        // Add \" Wonderland\" to values with key \"name\" that has no \"pets\" in their path\n        $jVal = new JString($jVal-\u003eval() . ' Wonderland');\n    }\n    return $jVal;\n};\n\n// true\nassert(\n    json_encode(json_decode($expectedJson))\n    ===\n    json_encode(JGami::map($f, json_decode($json)))\n);\n```\n\nModification of values is restricted to leaf nodes. This preserves structural integrity. The only exception is extending leaf nodes as seem by the following example:\n\n```php\n$json = '{\n    \"metadata\": \"To be filled\"\n}';\n\n$expectedJson = '{\n    \"metadata\": {\n        \"species\": \"Human\",\n        \"planet\": \"Earth\",\n        \"galacticLevel\": 3,\n        \"note\": \"Observe only\"\n    }\n}';\n\n$f = function (Node $node): JVal {\n    $jVal = $node-\u003ejVal();\n    if ($node-\u003ekey()-\u003eeq('metadata')) {\n        // Metadata, provided by our galactic overlords\n        $val = O::from([\n            'species'       =\u003e 'Human',\n            'planet'        =\u003e 'Earth',\n            'galacticLevel' =\u003e 3,\n            'note'          =\u003e 'Observe only',\n        ]);\n        // Replace the existing string value with the above object\n        return new JObject($val);\n    }\n    return $jVal;\n};\n// true\nassert(\n    json_encode(json_decode($expectedJson))\n    ===\n    json_encode(JGami::map($f, json_decode($json)))\n);\n```\n\nThis preserves existing structure while extending it with a new substructure.\n \n## How it works\n\nTBD\n\n## Tests\n\n\t$ composer utest\n\t$ composer phpcs\n\t$ composer phpstan\n\t$ composer infection\n\n## Changelog\n\n[Click here](changelog.md)\n\n## Licence\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwm%2Fjgami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwm%2Fjgami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwm%2Fjgami/lists"}