From cd8394716e7fa4f2660f0964cfdf7e27d88ca26b Mon Sep 17 00:00:00 2001 From: Reinfi Date: Sat, 21 Jan 2023 14:44:55 +0100 Subject: [PATCH] Allow undefined property handler to return a string to override variable name This lets us add e.g. camel case mapping handlers. Resolves: https://github.com/cweiske/jsonmapper/pull/198 Resolves: https://github.com/cweiske/jsonmapper/pull/183 Resolves: https://github.com/cweiske/jsonmapper/pull/150 Resolves: https://github.com/cweiske/jsonmapper/issues/149 Resolves: https://github.com/cweiske/jsonmapper/pull/29 --- README.rst | 22 +++++++++++++++++ src/JsonMapper.php | 12 +++++++-- tests/NameMappingTest.php | 52 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tests/NameMappingTest.php diff --git a/README.rst b/README.rst index 663503978..4c0bc3a23 100644 --- a/README.rst +++ b/README.rst @@ -391,6 +391,28 @@ __ http://php.net/manual/en/language.types.callable.php $jm->undefinedPropertyHandler = 'setUndefinedProperty'; $jm->map(...); +Or if you would let JsonMapper handle the setter for you, you can return a string +from the ``$undefinedPropertyHandler`` which will be used as property name. + +.. code:: php + + /** + * Handle undefined properties during JsonMapper::map() + * + * @param object $object Object that is being filled + * @param string $propName Name of the unknown JSON property + * @param mixed $jsonValue JSON value of the property + * + * @return void + */ + function fixPropName($object, $propName, $jsonValue) + { + return ucfirst($propName); + } + + $jm = new JsonMapper(); + $jm->undefinedPropertyHandler = 'fixPropName'; + $jm->map(...); Missing properties ------------------ diff --git a/src/JsonMapper.php b/src/JsonMapper.php index 56c963129..af68e54c1 100644 --- a/src/JsonMapper.php +++ b/src/JsonMapper.php @@ -177,10 +177,15 @@ public function map($json, $object) . ' in object of type ' . $strClassName ); } else if ($this->undefinedPropertyHandler !== null) { - call_user_func( + $undefinedPropertyKey = call_user_func( $this->undefinedPropertyHandler, $object, $key, $jvalue ); + + if (is_string($undefinedPropertyKey)) { + list($hasProperty, $accessor, $type, $isNullable) + = $this->inspectProperty($rc, $undefinedPropertyKey); + } } else { $this->log( 'info', @@ -188,7 +193,10 @@ public function map($json, $object) array('property' => $key, 'class' => $strClassName) ); } - continue; + + if (!$hasProperty) { + continue; + } } if ($accessor === null) { diff --git a/tests/NameMappingTest.php b/tests/NameMappingTest.php new file mode 100644 index 000000000..0b5c32eb0 --- /dev/null +++ b/tests/NameMappingTest.php @@ -0,0 +1,52 @@ +undefinedPropertyHandler = function ( + JsonMapperTest_Simple $object, + string $key, + $value + ): string { + return lcfirst( + str_replace( + ' ', '', ucwords(str_replace(array('_', '-'), ' ', $key)) + ) + ); + }; + + /** @var JsonMapperTest_Simple $sn */ + $sn = $jm->map( + json_decode('{"hyphen_value": "abc"}'), + new JsonMapperTest_Simple() + ); + + self::assertSame('abc', $sn->hyphenValue); + } + + public function testItDoesNotMapKeyIfUndefinedPropertyHandlerDoesNotReturnValue(): void + { + $jm = new JsonMapper(); + $jm->undefinedPropertyHandler = function ( + JsonMapperTest_Simple $object, + string $key, + $value + ): void {}; + + /** @var JsonMapperTest_Simple $sn */ + $sn = $jm->map( + json_decode('{"hyphen_value": "abc"}'), + new JsonMapperTest_Simple() + ); + + self::assertNull($sn->hyphenValue); + } +}