JSON is the format I use the most when it comes to data transfer. In almost every case I serialize my data with json_encode
and at some point in time I use json_decode
to get the data back into a somehow structured format.
For example I’m trying to encode/decode a class called Person
. The encoding part is easy, add the JsonSerializable
interface to the model and implement the JsonSerialize
method, call json_encode
on a model instance and you are done.
But the decoding confronts me with the same issue everytime I need to decode JSON data. json_decode
returns the decoded data in an object of type stdClass
or if you use the assoc
parameter the data gets stored in an array.
In most situations both approaches are not useful because you need objects with the initial type (especially if you are using PHP7 type hints ❤️️).
To solve this issue I implement some sort of conversion everytime I’m trying to decode data back into its original model. A few weeks ago I was hacked of to do this sh** again and I decided to write a PHP package called json-decoder.
The package should provide me with an easy mechanism to transform JSON into a PHP model instance. For the standard case (json field name equals property name) no further configuration should be necessary and if I want to transform a more complex type I should be able to define a Tranformer for it.
Let’s reuse the mentioned Person
class from above.
<?php
class Person {
public $firstname;
public $lastname;
}
The JSON data will look like this:
{
"firstname": "John",
"lastname": "Doe"
}
To tranform the data into an instance of Person
the following 3 lines of code are necessary:
<?php
$jsonDecoder = new JsonDecoder();
$jsonData = '{"firstname": "John", "lastname": "Doe"}';
$person = $jsonDecoder->decode($jsonData, Person::class);
Tranformers are necessary to define data types of a nested property. For example the Person
class has a field called address
which is of type Address
.
The basic example above would add the JSON data as an array to the address field
. To get the correct type you can define a so called Transformer
:
<?php
class PersonTransformer implements Transformer {
public function register(ClassBindings $classBindings)
{
$classBindings->register(new FieldBinding('address', 'address', Address::class);
}
public function transforms()
{
return Person::class;
}
}
The Transformer
interface defines two methods for registering your field bindings and also for the information which class type it can transform.
As you can see the standard case from the basic example gets also handled out of the box, that means no configuration for the firstname
and lastname
fields are necessary.
I’ve now used the package in two of my latest projects and I’m quite happy with the implementation. In the next time I’m going to add some small improvements to the code and also install the CI pipeline on the project. I think this package is interesting for many people so please help me to get it out and known to them by spreading the word.