pwm / jgami
Map functions over JSON.
0.5.0
2018-10-26 19:22 UTC
Requires
- php: >=7.2.0
- pwm/treegami: ^1.0
Requires (Dev)
- infection/infection: ^0.8.2
- phpstan/phpstan: ^0.7.0
- phpunit/phpunit: ^6.1
- squizlabs/php_codesniffer: ^3.0
README
Have you ever mapped a function over a list? Now you can do the same with JSON!
JGami provides a simple API to update values in arbitrarily complex JSON structures while preserving structural integrity.
Table of Contents
Requirements
PHP 7.2+
Installation
$ composer require pwm/jgami
Usage
It'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:
// What we have $json = '{ "name": "Alice", "age": 27, "likes": [ "Types", "Graphs", "Nature" ], "job": { "title": "Developer", "company": "Acme Corp." }, "pets": [ { "name": ["Woof"], "type": "Dog" }, { "name": ["Mr. Grumpy", "Mrs. Grumpy"], "type": "Cat" } ] }'; // What we want $expectedJson = '{ "name": "Alice Wonderland", "age": 37, "likes": [ "Types", "Trees", "Nature" ], "job": { "title": "Developer", "company": "Acme Corp." }, "pets": [ { "name": ["Woof <3"], "type": "Dog" }, { "name": ["Mr. Grumpy <3", "Mrs. Grumpy <3"], "type": "Cat" } ] }'; // Our update function, to be mapped over our JSON data // It takes a Node and return a JVal ie. a json value $f = function (Node $node): JVal { $jVal = $node->jVal(); if ($jVal->val() === 'Graphs') { // Replace "Graphs" with "Trees" $jVal = new JString('Trees'); } elseif ($node->key()->eq('age')) { // Add 10 to values with key "age" $jVal = new JInt($jVal->val() + 10); } elseif ($node->path()->hasAll('pets', 'name')) { // Add " <3" to values in paths with "pets" and "name" $jVal = new JString($jVal->val() . ' <3'); } elseif ($node->path()->hasNone('pets') && $node->key()->eq('name')) { // Add " Wonderland" to values with key "name" that has no "pets" in their path $jVal = new JString($jVal->val() . ' Wonderland'); } return $jVal; }; // true assert( json_encode(json_decode($expectedJson)) === json_encode(JGami::map($f, json_decode($json))) );
Modification of values is restricted to leaf nodes. This preserves structural integrity. The only exception is extending leaf nodes as seem by the following example:
$json = '{ "metadata": "To be filled" }'; $expectedJson = '{ "metadata": { "species": "Human", "planet": "Earth", "galacticLevel": 3, "note": "Observe only" } }'; $f = function (Node $node): JVal { $jVal = $node->jVal(); if ($node->key()->eq('metadata')) { // Metadata, provided by our galactic overlords $val = O::from([ 'species' => 'Human', 'planet' => 'Earth', 'galacticLevel' => 3, 'note' => 'Observe only', ]); // Replace the existing string value with the above object return new JObject($val); } return $jVal; }; // true assert( json_encode(json_decode($expectedJson)) === json_encode(JGami::map($f, json_decode($json))) );
This preserves existing structure while extending it with a new substructure.
How it works
TBD
Tests
$ composer utest
$ composer phpcs
$ composer phpstan
$ composer infection