[{"slug":"abstracts","title":"Abstract classes","content":"Abstract classes\n\nJsonMapper can support abstract types but requires a factory to be registered which can map the data to\nthe correct concrete implementation of the abstract class. During the building phase of the JsonMapper\ninstance you can use the\\JsonMapper\\Handler\\FactoryRegistry which is the second parameter\n($nonInstantiableTypeResolver) to the \\JsonMapper\\Handler\\PropertyMapper constructor.\n\nExample\naddFactory(\n\\App\\Shapes\\AbstractShape::class,\nnew \\App\\Shapes\\ShapeInstanceFactory()\n);\n\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withPropertyMapper(new \\JsonMapper\\Handler\\PropertyMapper(null, $nonInstantiableTypeResolver))\n    ->withDocBlockAnnotationsMiddleware()\n    ->withNamespaceResolverMiddleware()\n    ->build();\n\n$object = new \\App\\Shapes\\AbstractShapeWrapper();\n$mapper->mapObjectFromString('{\"shape\": {\"type\": \"square\", \"width\": 5, \"length\": 6}}', $object);\n\n_AbstractShape, AbstractShapeWrapper and ShapeInstanceFactory above stand in for your own classes. A\nworking equivalent can be found in the integration test._","destination":"abstracts"},{"slug":"casting-values","title":"Casting values","content":"Casting values\n\nJsonMapper out of the box will come with a ScalarCaster configured to cast values to the following types:\nboolean, integer, string, float and mixed. These casts are applied in order to match the\nproperties of the class you're trying to map to.\n\nAlternatively you can configure your mapper with the StrictScalarCaster. This caster will throw an\nexception when the type of the JSON value doesn't match the type of the property you're trying to map to.\n\nThe StrictScalarCaster and the PropertyMapperBuilder used below are available since JsonMapper 2.10.0\n\nwithScalarCaster(new \\JsonMapper\\Helpers\\StrictScalarCaster())\n    ->build();\n\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withPropertyMapper($propertyMapper)\n    ->withDocBlockAnnotationsMiddleware()\n    ->withTypedPropertiesMiddleware()\n    ->build();","destination":"casting-values"},{"slug":"interfaces","title":"Interfaces","content":"Interfaces\n\nJsonMapper can support interface types but requires a factory to be registered which can map the data to\nthe concrete type of the interface. During the building phase of the JsonMapper\ninstance you can use the\\JsonMapper\\Handler\\FactoryRegistry which is the first parameter\n($classFactoryRegistry) to the \\JsonMapper\\Handler\\PropertyMapper constructor.\n\nExample\naddFactory(\n\\Carbon\\CarbonInterface::class,\nfunction ($date) { return new \\Carbon\\Carbon($date); }\n);\n\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withPropertyMapper(new \\JsonMapper\\Handler\\PropertyMapper($classFactoryRegistry))\n    ->withDocBlockAnnotationsMiddleware()\n    ->withTypedPropertiesMiddleware()\n    ->withNamespaceResolverMiddleware()\n    ->build();","destination":"interfaces"},{"slug":"performance","title":"Performance","content":"Performance\n\nThe JsonMapper library has not only been build for comfort but also taking performance into account. This\npage touches some of the performance improvements you could consider based on the needs.\n\nLarge arrays\nIf your planning to map large arrays using this library it might be very helpful to tweak your JsonMapper\nobject to best fit your needs. As an example the JsonMapperFactory will load both the DocBlock Annotations\nand the Types Properties middleware which do the same for different version of the PHP runtime.\n\nLarge nested objects\nWhen dealing with large nested objects it could help the performance it you where to load the property map up front. This could easily be achieved using\na custom middleware where the property map is populated with written out property information.","destination":"performance"},{"slug":"architecture","title":"Architecture","content":"Architecture\n\nMiddleware\nThe core of JsonMapper is build using the chain of responsibility pattern allowing multiple\nmiddleware being added to the mapper. This pattern allows for easy customisation for each\nindividual project.\nThis also allows for custom middleware to meet edge cases not offered in the middleware that is par of JsonMapper.\n\n$cache = new \\JsonMapper\\Cache\\ArrayCache();\n$mapper = new \\JsonMapper\\JsonMapper(new \\JsonMapper\\Handler\\PropertyMapper());\n\n\/* Push included middleware onto the mapper *\/\n$mapper->push(new \\JsonMapper\\Middleware\\DocBlockAnnotations($cache));\n$mapper->push(new \\JsonMapper\\Middleware\\NamespaceResolver($cache));\n\n\/* Add custom middleware *\/\n$mapper->push(new class extends \\JsonMapper\\Middleware\\AbstractMiddleware {\npublic function handle(\n\\stdClass $json,\n\\JsonMapper\\Wrapper\\ObjectWrapper $object,\n\\JsonMapper\\ValueObjects\\PropertyMap $map,\n\\JsonMapper\\JsonMapperInterface $mapper\n): void {\n\/* Custom logic here *\/\n}\n});\n\nSupported PHP versions\nJsonMapper currently supports PHP versions 7.4 and higher.","destination":"architecture"},{"slug":"creating-middleware","title":"Creating middleware","content":"Creating middleware\n\nOne of the great things about JsonMapper is that it is highly extensible. If the out-of-the-box middleware don't meet\nyour specific needs, it's very easy to create your own custom middleware to handle your specific use case.\n\nTo create your own middleware, you need to define a class that implements JsonMapper\\Middleware\\MiddlewareInterface.\nThe easiest way to do so is to extend JsonMapper\\Middleware\\AbstractMiddleware, which leaves you a single method to\nimplement: handle(). It receives the JSON data, the object being mapped, the property map built so far, and the mapper\nitself, and amends them in place rather than returning anything.\n\nHere's an example of how to create a simple middleware that converts a JSON string to an array before it's mapped to\na PHP class:\n\nuse JsonMapper\\Middleware\\AbstractMiddleware;\nuse JsonMapper\\JsonMapperInterface;\nuse JsonMapper\\ValueObjects\\PropertyMap;\nuse JsonMapper\\Wrapper\\ObjectWrapper;\n\nclass CustomMiddleware extends AbstractMiddleware\n{\npublic function handle(\n\\stdClass $json,\nObjectWrapper $object,\nPropertyMap $propertyMap,\nJsonMapperInterface $mapper\n): void\n{\n\/\/ Custom logic goes here.\n}\n}\n\nOnce you've created your custom middleware, you can add it to the middleware stack with the builder's withMiddleware\nmethod, like this:\n\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withDocBlockAnnotationsMiddleware()\n    ->withTypedPropertiesMiddleware()\n    ->withMiddleware(new CustomMiddleware())\n    ->build();","destination":"creating-middleware"},{"slug":"getting-started","title":"Getting started","content":"Getting started\n\nThis guide will explain how to get started with JsonMapper. With JsonMapper the goal is to map a JSON response to a PHP object.\nIn this guide we will be using the Chuck Norris facts API. For more details on the API see https:\/\/api.chucknorris.io\n\nIn order to get the JSON data we need to call https:\/\/api.chucknorris.io\/jokes\/random which will return the following\nstructure:\n{\n\"icon_url\" : \"https:\/\/assets.chucknorris.host\/img\/avatar\/chuck-norris.png\",\n\"id\" : \"1UfPOdHSTvqXGQWlqfyoKw\",\n\"url\" : \"https:\/\/api.chucknorris.io\/jokes\/1UfPOdHSTvqXGQWlqfyoKw\",\n\"value\" : \"Chuck Norris doesn't get old, he levels up.\"\n}\n\nFrom that structure a PHP object can be derived\nbestFit();\n$chuckNorrisFact = new ChuckNorrisFact();\n\n\/\/ Map the data using JsonMapper\n$mapper->mapObjectFromString($data, $chuckNorrisFact);","destination":"getting-started"},{"slug":"laravel-usage","title":"Laravel usage","content":"Laravel usage\n\nIn order to use JsonMapper with your Laravel{:target=\"_blank\"} application you only need\nJsonMapper's LaravelPackage{:target=\"_blank\"}.\n\nInstallation\nThe installation of JsonMapper Laravel package can easily be done with Composer{:target=\"_blank\"}\n$ composer require json-mapper\/laravel-package\nThis package makes use of Laravels package auto-discovery mechanism{:target=\"_blank\"}.\n\n * The example shown above assumes that composer is on your $PATH. \n\nConfiguration\nCopy the package config to your local config with the publish command:\nphp artisan vendor:publish --provider=\"JsonMapper\\LaravelPackage\\ServiceProvider\"\nThe package config enables you to choose between the default JsonMapper or the best-fit JsonMapper.\nYou can check the Setup page for more info of the different types.\n\nExample\nmapper->mapToCollectionFromString($data, new Todo());\n}\n}\n\nclass Todo\n{\npublic int $userId;\npublic int $id;\npublic string $title;\npublic bool $completed;\n}","destination":"laravel-usage"},{"slug":"symfony-usage","title":"Symfony usage","content":"Symfony usage\n\nIn order to use JsonMapper with your Symfony{:target=\"_blank\"} application you only need\nJsonMapper's SymfonyBundle{:target=\"_blank\"}.\n\nInstallation\nThe installation of JsonMapper Symfony package can easily be done with Composer{:target=\"_blank\"}\n$ composer require json-mapper\/symfony-bundle\nThe example shown above assumes that composer is on your $PATH.\n\nConfiguration\nIf your application does not use Symfony Flex{:target=\"_blank\"}, you need to manually enable the bundle in your config\/bundles.php file:\n['all' => true],\n];\n\nExample\nNow JsonMapper will be automatically injected if it is provided as one of the constructor arguments.\n\nmapper = $mapper;\n}\n}","destination":"symfony-usage"},{"slug":"index","title":"Documentation","content":"Documentation\n\nJsonMapper maps JSON data to PHP classes through a chain of middleware that you arrange to suit your\nown models. These pages cover installing it, the middleware it ships with, and how to extend it.\n\nNew here? Start with Getting started, which walks through mapping a\nfirst response end to end.\n\nThese pages describe JsonMapper 2.25.1, which requires PHP 7.4 or higher. Anything added during\nthe 2.x line carries an \"Available since\" line naming the release that introduced it; everything else\nhas been there since 2.0.\n\nWhere to look\n\nInstallation* and Setup* \u2014 add the\npackage to your project and create a mapper instance.\nArchitecture** \u2014 how the middleware chain fits together. Worth reading\nbefore writing your own.\nGuides** \u2014 end-to-end walkthroughs, including\ncreating middleware and using JsonMapper with\nLaravel or Symfony.\nMiddleware** \u2014 a page per middleware, from\ntyped properties and\nDocBlock annotations through to\nrenaming and value transformation.\nAdvanced Usage** \u2014 performance,\ncasting values, and mapping to\ninterfaces and\nabstract classes.\n\nEvery page has an \"Edit Source\" link if you spot something worth improving.","destination":""},{"slug":"attributes","title":"PHP 8.0 Attributes","content":"PHP 8.0 Attributes\n\nThe attributes middleware uses the PHP 8.0 attributes to map JSON data from names that do not match the model.\nThis way your code doesn't need to follow the same naming convention as the JSON API exposes.\n\nclass User\n{\n#[\\JsonMapper\\Middleware\\Attributes\\MapFrom(\"Identifier\")]\npublic int $id;\n#[\\JsonMapper\\Middleware\\Attributes\\MapFrom(\"UserName\")]\npublic string $name;\n}\n\n$cache = new \\JsonMapper\\Cache\\NullCache();\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->create(\nnew \\JsonMapper\\Handler\\PropertyMapper(),\nnew \\JsonMapper\\Middleware\\Attributes\\Attributes(),\nnew \\JsonMapper\\Middleware\\TypedProperties($cache)\n);\n$object = new User();\n\n$mapper->mapObjectFromString('{ \"UserName\": \"John Doe\", \"Identifier\": 42 }', $object);\n\necho $object->id; \/\/ 42\necho $object->name; \/\/ \"John Doe\"","destination":"attributes"},{"slug":"case-conversion","title":"Case conversion","content":"Case conversion\n\nThe case conversion middleware can map from a specific text notation to another text notation.\nThis way your code doesn't need to follow the same text notation as the JSON API exposes.\n\nclass User\n{\n\/* @var string \/\npublic $name;\n}\n\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->default();\n\nAdd the middleware to convert from studly caps to camel case\n$mapper->push(new \\JsonMapper\\Middleware\\CaseConversion(\n\\JsonMapper\\Enums\\TextNotation::STUDLY_CAPS(),\n\\JsonMapper\\Enums\\TextNotation::CAMEL_CASE()\n));\n\n$object = new User();\n$mapper->mapObjectFromString('{ \"Name\": \"John Doe\" }', $object);\n\necho $object->name; \/\/ \"John Doe\"\n\nThe case conversion middleware currently supports the following text notations:\nStudly caps**\nCamel case**\nUnderscore**\nKebab case**","destination":"case-conversion"},{"slug":"constructor","title":"Constructor","content":"Constructor\n\nThe constructor middleware uses reflection to register a custom factory to the factory registry\nwhich can utilise the class constructor. This enables the use of custom constructors without having to manually write factories. This feature\ncan be combined with the readonly properties introduced with PHP 8.1.\n\nAvailable since JsonMapper 2.14.0\n\nclass User\n{\npublic function __construct(\npublic readonly string $name,\n) {}\n}\n\n$factoryRegistry = new \\JsonMapper\\Handler\\FactoryRegistry();\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withDocBlockAnnotationsMiddleware()\n    ->withObjectConstructorMiddleware($factoryRegistry)\n    ->withPropertyMapper(new \\JsonMapper\\Handler\\PropertyMapper($factoryRegistry))\n    ->build();\n\n$object = $mapper->mapToClassFromString('{ \"name\": \"John Doe\" }', User::class);\n\necho $object->name; \/\/ \"John Doe\"","destination":"constructor"},{"slug":"debugging","title":"Debugging","content":"Debugging\n\nThe debugging middleware allows you to log the current state of the ongoing map method.\nThe state of the json and object inputs as well as the property map will be logged to an PSR-3 compliant{:target=\"_blank\"} logger\n\nclass User\n{\n\/* @var string \/\npublic $name;\n}\n\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->default();\n\nAdd the debug middleware with any PSR-3 compliant logger\n$logger = new \\Monolog\\Logger('json-mapper');\n$logger->pushHandler(new \\Monolog\\Handler\\StreamHandler('php:\/\/stdout'));\n$mapper->push(new \\JsonMapper\\Middleware\\Debugger($logger));\n\n$object = new User();\n$mapper->mapObjectFromString('{ \"name\": \"John Doe\" }', $object);\n\nWhat gets logged\n\nEach object that passes through the middleware produces one record at debug level, with the message\nCurrent state attributes passed through JsonMapper middleware and three context entries:\n\nKey Contents\n\njson The JSON for the object currently being mapped, re-encoded as a string\nobject The name of the class being mapped onto\npropertyMap The property map as it stood when the middleware ran, as a JSON string\n\nThe example above logs:\n\n[debug] Current state attributes passed through JsonMapper middleware\njson: {\"name\":\"John Doe\"}\nobject: User\npropertyMap: {\"properties\":{\"name\":{\"name\":\"name\",\"types\":[{\"type\":\"string\",\"isArray\":false,\"arrayInformation\":{\"isArray\":false,\"dimensions\":0}}],\"visibility\":\"public\",\"isNullable\":false}}}\n\nThe property map is the interesting part, and it is easier to read reformatted. It records the type\neach middleware resolved for every property, which is what to check when a property is silently left\nunset:\n\n{\n\"properties\": {\n\"name\": {\n\"name\": \"name\",\n\"types\": [\n{\n\"type\": \"string\",\n\"isArray\": false,\n\"arrayInformation\": { \"isArray\": false, \"dimensions\": 0 }\n}\n],\n\"visibility\": \"public\",\n\"isNullable\": false\n}\n}\n}\n\nWhere you place the middleware matters\n\nThe property map is built up by the middleware ahead of the debugger in the chain, so the position you\nadd it in decides what you see.\n\npush() puts it last, after the middleware that populate the map have run, which is what you usually\nwant \u2014 the map is fully resolved, as above.\n\nunshift() puts it first, before anything has contributed, and the map is still empty:\n\n[debug] Current state attributes passed through JsonMapper middleware\njson: {\"name\":\"John Doe\"}\nobject: User\npropertyMap: {\"properties\":[]}\n\nThat is the view to use when you want the raw JSON as it arrived, before any renaming or case\nconversion middleware has altered it.\n\nNested objects\n\nThe middleware runs once per object, not once per mapping call, so a nested structure produces a\nrecord for each object. Mapping { \"name\": \"John Doe\", \"address\": { \"city\": \"Amsterdam\" } } onto a\nPerson holding an Address logs the outer object first and then the inner one (the propertyMap\nentry is elided here):\n\n[debug] Current state attributes passed through JsonMapper middleware\njson: {\"name\":\"John Doe\",\"address\":{\"city\":\"Amsterdam\"}}\nobject: Person\npropertyMap: ...\n\n[debug] Current state attributes passed through JsonMapper middleware\njson: {\"city\":\"Amsterdam\"}\nobject: Address\npropertyMap: ...","destination":"debugging"},{"slug":"doc-block-annotations","title":"DocBlock annotations","content":"DocBlock annotations\n\nThe DocBlock annotations middleware will scan the target object using Reflection{:target=\"_blank\"}\nfor properties and their DocBlock{:target=\"_blank\"}  annotations.\nUsing the annotations it will determine the property type and amend these results to the property map.\nThe property map is utilised by the PropertyMapper when applying the data from the JSON object to the target object.\n\nThis middleware is part of both the default and best fit factory methods as it provides elementary functionality to JsonMapper\n\nSupported docblock types\n\nThe following @var annotation formats are supported:\n\nFormat Description Example\n\nType A single value of the given type @var string\nType[] An array of the given type @var int[]\nType A multi-dimensional array of the given type @var string\nlist A list of the given type @var list\narray An array of the given type @var array\narray An array keyed by TKey with values of TValue @var array\n\nExample\ndefault();\n\n$object = new Joke();\n$jsonString = filegetcontents('https:\/\/official-joke-api.appspot.com\/jokes\/random');\n\n$mapper->mapObjectFromString($jsonString, $object);\n\necho $object->setup; \/\/ \"What do you call a pile of cats?\"\necho $object->punchline; \/\/ \"A Meowtain.\"\n\nclass Joke\n{\n\/* @var int \/\npublic $id;\n\/* @var string \/\npublic $type;\n\/* @var string \/\npublic $setup;\n\/* @var string \/\npublic $punchline;\n}\n\nArray types example\n\nThe middleware supports multiple ways to annotate array and list properties:\n\n *\/\npublic $tagList;\n\n\/* @var array \/\npublic $tagArray;\n\n\/* @var array \/\npublic $tagMap;\n}\n\nclass Tag\n{\n\/* @var string \/\npublic $name;\n}","destination":"doc-block-annotations"},{"slug":"final-callback","title":"Final callback","content":"Final callback\n\nUsing the final callback middleware it is possible to invoke a callback because you might need to initialise some method on your model or perhaps want to put it into cache.\n\nclass User\n{\n\/* @var string \/\npublic $name;\n\npublic function done(): void\n{\n\/\/ Whatever your model needs once it has been filled.\n}\n}\n\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->default();\n\nAdd the callback middleware\n$mapper->push(new \\JsonMapper\\Middleware\\FinalCallback(function(\n\\stdClass $json,\n\\JsonMapper\\Wrapper\\ObjectWrapper $object,\n\\JsonMapper\\ValueObjects\\PropertyMap $map,\n\\JsonMapper\\JsonMapperInterface $mapper\n) {\n\/\/ Call a method on the object\n$object->getObject()->done();\n\/\/ Or persist it in the cache\nCache::put('key', $object->getObject(), $seconds);\n}));\n\n$object = new User();\n$mapper->mapObjectFromString('{ \"name\": \"John Doe\" }', $object);\n\nThe callback is applied to the top level object only. Pass false as the second constructor\nargument to have it invoked for nested objects as well.","destination":"final-callback"},{"slug":"laravel-eloquent","title":"Laravel Eloquent","content":"Laravel Eloquent\n\nThe Laravel Eloquent middleware allows you to map JSON data into a Laravel Eloquent model. The middleware uses the power of the\nEloquent features such as automatic database column support, dates and casts.\n\nSaving the data returned from an url as Eloquent models can be achieved with the following code:\nbestFit();\n$mapper->push(new \\JsonMapper\\EloquentMiddleware\\EloquentMiddleware(new \\JsonMapper\\Cache\\ArrayCache()));\n\n$licenses = $mapper->mapArrayFromString($data, new License());\n\\Illuminate\\Support\\Collection::make($licenses)->each(fn(License $l) => $l->save());\n\nThis middleware is part of separate repository and need to be installed using composer require json-mapper\/eloquent-middleware","destination":"laravel-eloquent"},{"slug":"namespace-resolver","title":"Namespace resolver","content":"Namespace resolver\n\nThe namespace resolver middleware will tokenize the target object using nikic\/php-parser{:target=\"_blank\"}\nin order to get the namespaces that are imported.  These imports will be applied to the object properties found in the property map.\n\nThis middleware is part of both the default and best fit factory methods as it provides elementary functionality to JsonMapper\n\nExample\ndefault();\n\n$object = new Response();\n$jsonString = filegetcontents('https:\/\/api.chucknorris.io\/jokes\/search?query=programming');\n\n$mapper->mapObjectFromString($jsonString, $object);\n\necho $object->result[0]->value; \/\/ \"Chuck Norris insists on strongly-typed programming languages.\"\n\n<?php\n\nnamespace App\\Api\\Joke;\n\nuse App\\Dto\\Joke;\n\nclass Response\n{\n\/* @var int \/\npublic $total;\n\/* @var Joke[] \/\npublic $result;\n}\n\n<?php\n\nnamespace App\\Dto;\n\nclass Joke\n{\n\/* @var int \/\npublic $value;\n}","destination":"namespace-resolver"},{"slug":"rename","title":"Rename","content":"Rename\n\nThe rename middleware uses an explicit defined mapping to rename JSON properties in order\nto match your model's naming convention. This way your code doesn't need to follow the same\nnaming convention as the JSON API exposes.\n\nAvailable since JsonMapper 2.2.0\n\nclass User\n{\npublic int $id;\npublic string $name;\n}\n\n$rename = new \\JsonMapper\\Middleware\\Rename\\Rename();\n$rename->addMapping(User::class, 'Full-Name', 'name');\n$rename->addMapping(User::class, 'Identifier', 'id');\n\nOr you can pass the mappings straight to the constructor\n$rename = new \\JsonMapper\\Middleware\\Rename\\Rename(\nnew \\JsonMapper\\Middleware\\Rename\\Mapping(User::class, 'Full-Name', 'name'),\nnew \\JsonMapper\\Middleware\\Rename\\Mapping(User::class, 'Identifier', 'id')\n);\n\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->bestFit();\n$mapper->unshift($rename);\n$object = new User();\n\n$mapper->mapObjectFromString('{ \"Full-Name\": \"John Doe\", \"Identifier\": 42 }', $object);\n\necho $object->id; \/\/ 42\necho $object->name; \/\/ \"John Doe\"","destination":"rename"},{"slug":"typed-properties","title":"Typed properties","content":"Typed properties\n\nThe typed properties middleware will scan the target object using Reflection{:target=\"_blank\"}\nfor properties.\nUsing the reflection information it will determine the property type and amend these results to the property map.\nThe property map is utilised by the PropertyMapper when applying the data from the JSON object to the target object.\n\nThis middleware is part of the best fit factory method as it provides elementary functionality to JsonMapper\n\nExample\nbestFit();\n\n$object = new Joke();\n$jsonString = filegetcontents('https:\/\/official-joke-api.appspot.com\/jokes\/random');\n\n$mapper->mapObjectFromString($jsonString, $object);\n\necho $object->setup; \/\/ \"What do you call a pile of cats?\"\necho $object->punchline; \/\/ \"A Meowtain.\"\n\nclass Joke\n{\npublic int $id;\npublic string $type;\npublic string $setup;\npublic string $punchline;\n}","destination":"typed-properties"},{"slug":"value-transformation","title":"Value Transformation","content":"Value Transformation\n\nThe value transformation middleware can be used to apply a callback to the JSON value before it is mapped to the class property.\n\nAvailable since JsonMapper 2.9.0\n\nThe examples below map onto the following class:\n\nclass User\n{\npublic string $name;\n}\n\nUsing a php named function as callback\n$middleware = new \\JsonMapper\\Middleware\\ValueTransformation('strtolower');\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->bestFit();\n$mapper->unshift($middleware);\n$object = new User();\n\n$mapper->mapObjectFromString('{ \"name\": \"JOHN DOE\" }', $object);\n\necho $object->name; \/\/ \"john doe\"\n\nUsing a custom callback\n\nPass true as the second constructor argument to have the property name handed to the\ncallback alongside the value.\n\n$middleware = new \\JsonMapper\\Middleware\\ValueTransformation(\nstatic function ($key, $value) {\nif ($key === 'name') {\nreturn \\base64_decode($value);\n}\n\nreturn $value;\n},\ntrue\n);\n$mapper = (new \\JsonMapper\\JsonMapperFactory())->bestFit();\n$mapper->unshift($middleware);\n$object = new User();\n\n$mapper->mapObjectFromString('{ \"name\": \"Sm9obiBEb2U=\" }', $object);\n\necho $object->name; \/\/ \"John Doe\"","destination":"value-transformation"},{"slug":"installation","title":"Installation","content":"Installation\n\nThe installation of JsonMapper can easily be done with Composer{:target=\"_blank\"}\n$ composer require json-mapper\/json-mapper\nThe example shown above assumes that composer is on your $PATH.","destination":"installation"},{"slug":"setup","title":"Setup","content":"Setup\n\nQuick and easy setup\nSetting up JsonMapper for your project is simple. JsonMapper comes with a factory that\noffers three methods to create a JsonMapper instance.\n\ndefault();\n\n\/\/ Use bestFit to get the JsonMapper that fits best to your PHP runtime\n\/\/ version. Since PHP 7.4 is the minimum supported version, this always adds\n\/\/ the typed properties middleware on top of the default set.\n$bestFit = (new \\JsonMapper\\JsonMapperFactory())->bestFit();\n\nUse create to build an instance with your own property mapper and your own series of\nmiddleware. Unlike default and bestFit it adds no middleware of its own, so pass at\nleast one \u2014 building a mapper with an empty middleware chain throws a BuilderException.\n\ncreate(\nnew \\JsonMapper\\Handler\\PropertyMapper(),\nnew \\JsonMapper\\Middleware\\DocBlockAnnotations($cache),\nnew \\JsonMapper\\Middleware\\NamespaceResolver($cache)\n);\n\nTailored setup\nSince version 2.3.0 JsonMapper offers a JsonMapperBuilder class which can be used to have a more tailored\nsetup of your mapper instance. In version 2.10.0 the PropertyMapperBuilder was introduced. Below you can find\nan example that shows how you can create a JsonMapper instance using the builders.\n\nwithScalarCaster(new \\JsonMapper\\Helpers\\StrictScalarCaster())\n    ->build();\n\n$mapper = \\JsonMapper\\JsonMapperBuilder::new()\n    ->withJsonMapperClassName(YourExtendedJsonMapper::class)\n    ->withPropertyMapper($propertyMapper)\n    ->withDefaultCache(new \\JsonMapper\\Cache\\ArrayCache())\n    ->withDocBlockAnnotationsMiddleware()\n    ->build();\n\nBoth builders are created through a static new() method. The class passed to\nwithJsonMapperClassName() must implement \\JsonMapper\\JsonMapperInterface; the cache given\nto withDefaultCache() is handed to every middleware that is added without a cache of its own.","destination":"setup"}]