{"id":22109754,"url":"https://github.com/magicsunday/jsonmapper","last_synced_at":"2026-03-03T09:04:43.272Z","repository":{"id":62522464,"uuid":"333490427","full_name":"magicsunday/jsonmapper","owner":"magicsunday","description":"Map JSON to PHP","archived":false,"fork":false,"pushed_at":"2025-11-11T21:07:44.000Z","size":96,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-11T23:16:25.556Z","etag":null,"topics":["json","jsonmapper","mapper","php"],"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/magicsunday.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"custom":"https://paypal.me/magicsunday"}},"created_at":"2021-01-27T16:29:02.000Z","updated_at":"2025-02-03T13:15:16.000Z","dependencies_parsed_at":"2024-03-02T08:21:35.611Z","dependency_job_id":"1679e604-8c85-449e-afe8-1ce99682b734","html_url":"https://github.com/magicsunday/jsonmapper","commit_stats":{"total_commits":49,"total_committers":2,"mean_commits":24.5,"dds":0.04081632653061229,"last_synced_commit":"82378dc3a2bfa2db405bf9761b9c33af992b55bc"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/magicsunday/jsonmapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicsunday%2Fjsonmapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicsunday%2Fjsonmapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicsunday%2Fjsonmapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicsunday%2Fjsonmapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magicsunday","download_url":"https://codeload.github.com/magicsunday/jsonmapper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicsunday%2Fjsonmapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30038600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T06:58:30.252Z","status":"ssl_error","status_checked_at":"2026-03-03T06:58:15.329Z","response_time":61,"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","jsonmapper","mapper","php"],"created_at":"2024-12-01T09:39:00.994Z","updated_at":"2026-03-03T09:04:43.256Z","avatar_url":"https://github.com/magicsunday.png","language":"PHP","readme":"[![Latest version](https://img.shields.io/github/v/release/magicsunday/jsonmapper?sort=semver)](https://github.com/magicsunday/jsonmapper/releases/latest)\n[![License](https://img.shields.io/github/license/magicsunday/jsonmapper)](https://github.com/magicsunday/jsonmapper/blob/main/LICENSE)\n[![CI](https://github.com/magicsunday/jsonmapper/actions/workflows/ci.yml/badge.svg)](https://github.com/magicsunday/jsonmapper/actions/workflows/ci.yml)\n\n# JsonMapper\nThis module provides a mapper to map JSON to PHP classes utilizing Symfony's property info and access packages.\n\n## Installation\n\n### Using Composer\nTo install using [composer](https://getcomposer.org/), just run the following command from the command line.\n\n```bash\ncomposer require magicsunday/jsonmapper\n```\n\nTo remove the module run:\n```bash\ncomposer remove magicsunday/jsonmapper\n```\n\n\n## Usage\n### PHP classes\nIn order to guarantee a seamless mapping of a JSON response into PHP classes you should prepare your classes well.\nAnnotate all properties with the requested type.\n\nIn order to ensure correct mapping of a collection, the property has to be annotated using\nthe phpDocumentor collection annotation type. A collection is a non-scalar value capable of containing other\nvalues.\n\nFor example:\n\n```php\n@var SomeCollection\u003cDateTime\u003e\n@var SomeCollection\u003cstring\u003e\n@var Collection\\SomeCollection\u003cApp\\Entity\\SomeEntity\u003e\n```\n\n\n#### Custom annotations\nSometimes its may be required to circumvent the limitations of a poorly designed API. Together with custom\nannotations it becomes possible to fix some API design issues (e.g. mismatch between documentation and webservice\nresponse), to create a clean SDK.\n\n##### @MagicSunday\\JsonMapper\\Annotation\\ReplaceNullWithDefaultValue\nThis annotation is used to inform the JsonMapper that an existing default value should be used when\nsetting a property, if the value derived from the JSON is a NULL value instead of the expected property type.\n\nThis can be necessary, for example, in the case of a bad API design, if the API documentation defines a\ncertain type (e.g. array), but the API call itself then returns NULL if no data is available for a property\ninstead of an empty array that can be expected.\n\n```php\n/**\n * @var array\u003cstring\u003e\n *\n * @MagicSunday\\JsonMapper\\Annotation\\ReplaceNullWithDefaultValue\n */\npublic array $array = [];\n```\n\nIf the mapping tries to assign NULL to the property, the default value will be used, as annotated.\n\n##### @MagicSunday\\JsonMapper\\Annotation\\ReplaceProperty\nThis annotation is used to inform the JsonMapper to replace one or more properties with another one. It's\nused in class context.\n\nFor instance if you want to replace a cryptic named property to a more human-readable name.\n```php\n/**\n * @MagicSunday\\JsonMapper\\Annotation\\ReplaceProperty(\"type\", replaces=\"crypticTypeNameProperty\")\n */\nclass FooClass\n{\n    /**\n     * @var string\n     */\n    public $type;\n}\n```\n\n\n### Instantiation\n\nIn order to create an instance of the JsonMapper you are required to pass some arguments to the constructor. The\nconstructor requires an instance of `\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor` and an instance of\n`\\Symfony\\Component\\PropertyAccess\\PropertyAccessor`. The other arguments are optional.\n\nSo first create instances of Symfony's property info extractors. Each list of extractors could contain any number of \navailable extractors. You could also create your own extractors to adjust the process of extracting property info to \nyour needs.\n\nTo use the `PhpDocExtractor` extractor you need to install the `phpdocumentor/reflection-docblock` library too.\n\n```php\nuse \\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor;\nuse \\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor;\nuse \\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor;\nuse \\Symfony\\Component\\PropertyAccess\\PropertyAccessor;\n```\n\nA common extractor setup:\n```php\n$listExtractors = [ new ReflectionExtractor() ];\n$typeExtractors = [ new PhpDocExtractor() ];\n$propertyInfoExtractor = new PropertyInfoExtractor($listExtractors, $typeExtractors);\n```\n\nCreate an instance of the property accessor:\n```php\n$propertyAccessor = PropertyAccess::createPropertyAccessor();\n```\n\nUsing the third argument you can pass a property name converter instance to the mapper. With this you can convert \nthe JSON property names to you desired format your PHP classes are using.\n```php\n$nameConverter = new \\MagicSunday\\JsonMapper\\Converter\\CamelCasePropertyNameConverter();\n```\n\nThe last constructor parameter allows you to pass a class map to JsonMapper in order to change the default mapping \nbehaviour. For instance if you have an SDK which maps the JSON response of a webservice to PHP. Using the class map you could override\nthe default mapping to the SDK's classes by providing an alternative list of classes used to map.\n```php\n$classMap = [\n    SdkFoo::class =\u003e Foo::class,\n];\n```\n\nCreate an instance of the JsonMapper:\n```php\n$mapper = new \\MagicSunday\\JsonMapper(\n    $propertyInfoExtractor,\n    $propertyAccessor,\n    $nameConverter,\n    $classMap\n);\n```\n\nTo handle custom or special types of objects, add them to the mapper. For instance to perform\nspecial treatment if an object of type Bar should be mapped:\n```php\n$mapper-\u003eaddType(\n    Bar::class,\n    /** @var mixed $value JSON data */\n    static function ($value): ?Bar {\n        return $value ? new Bar($value['name']) : null;\n    }\n);\n```\n\nor add a handler to map DateTime values:\n```php\n$mapper-\u003eaddType(\n    \\DateTime::class,\n    /** @var mixed $value JSON data */\n    static function ($value): ?\\DateTime {\n        return $value ? new \\DateTime($value) : null;\n    }\n);\n```\n\nConvert a JSON string into a JSON array/object using PHPs built in method `json_decode`\n```php\n$json = json_decode('JSON STRING', true, 512, JSON_THROW_ON_ERROR);\n```\n\nCall method `map` to do the actual mapping of the JSON object/array into PHP classes. Pass the initial class name\nand optional the name of a collection class to the method.\n```php\n$mappedResult = $mapper-\u003emap($json, Foo::class, FooCollection::class);\n```\n\nA complete set-up may look like this:\n\n```php\n/**\n * Returns an instance of the JsonMapper for testing.\n *\n * @param string[]|Closure[] $classMap A class map to override the class names\n *\n * @return \\MagicSunday\\JsonMapper\n */\nprotected function getJsonMapper(array $classMap = []): \\MagicSunday\\JsonMapper\n{\n    $listExtractors = [ new ReflectionExtractor() ];\n    $typeExtractors = [ new PhpDocExtractor() ];\n    $extractor      = new PropertyInfoExtractor($listExtractors, $typeExtractors);\n\n    return new \\MagicSunday\\JsonMapper(\n        $extractor,\n        PropertyAccess::createPropertyAccessor(),\n        new CamelCasePropertyNameConverter(),\n        $classMap\n    );\n}\n```\n\n## Development\n\n### Testing\n```bash\ncomposer update\ncomposer ci:cgl\ncomposer ci:test\ncomposer ci:test:php:phplint\ncomposer ci:test:php:phpstan\ncomposer ci:test:php:rector\ncomposer ci:test:php:unit\n```\n","funding_links":["https://paypal.me/magicsunday"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicsunday%2Fjsonmapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagicsunday%2Fjsonmapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicsunday%2Fjsonmapper/lists"}