Working with JSON and Objects
PHP includes a simple, built-in JSON serializer with json_encode and json_decode. However, these functions create either a stdClass or array, and have no flexibility beyond that. Sometimes, you just want a little more power and flexibility. For those cases, FEAST includes a dynamic JSON marshaller.
The Components
The marshaller and unmarshaller functions
\Feast\Json
is a class containing two static methods; one for marshalling and one for unmarshalling. The marshal
method takes two parameters.
-
object
- the object to be marshalled into a json string. -
propertyTypesFlag
- int or null. See https://www.php.net/manual/en/class.reflectionproperty.php#reflectionproperty.constants.modifiers for values.
The unmarshal method takes three parameters.
-
data
- a json string -
objectOrClass
- either a class name or a pre-instantiated object. -
skipConstructor
- skip constructor call and instantiate object through reflection. This will also apply to any nested objects.
The Attribute
\Feast\Attributes\JsonItem
is a PHP8 attribute that is used to decorate properties in your class to specify
transformations on JSON data. It has four optional properties.
-
name
- specifies an alternate name to be used when serializing to JSON as well as the name of the key for this property when reading from the JSON string. If not supplied, the class property name will be used as the name. -
arrayOrCollectionType
- used as a decorator on arrays or\Feast\Collection\Collection
and its descendents to specify what the type contained inside a collection is. This can be used to mark a property as being a collection of another type. -
dateFormat
- Specifies the format to serialize into for objects of the\Feast\Date
class. Defaults to ISO-8601. -
included
- Defaults to true. If set to false, Json strings created with theJson::marshal
function will not include the property. -
omitEmpty
- Defaults to false. If set to true, Json strings created with theJson::marshal
function will not include the property if the value is null or empty string (''
).
Tying it together
Below is a sample class that can be used with the JSON marshaller.
class TestJsonItem
{
#[JsonItem(name: 'first_name')]
public string $firstName;
#[JsonItem(name: 'last_name')]
public string $lastName;
#[JsonItem(arrayOrCollectionType: TestJsonItem::class)]
public array $items;
#[JsonItem(dateFormat: 'Ymd')]
public Date $timestamp;
#[JsonItem(included: false)]
public string $notIncluded;
#[JsonItem(omitEmpty: true)]
public string $emptyNotIncluded = '';
This class has six properties. The first, $firstName
is a string, and is pulled from the first_name
key. The second
property is $lastName
and behaves the same as $firstName
. The third property is an array. This array contains other
items of the same class. These items will marshal or unmarshal through all layers. The fourth property is an instance
of \Feast\Date
. The fifth property, $notIncluded
is a string that is pulled from notIncluded
in the JSON, but will
NOT be marshalled back into JSON. The sixth property, $emptyNotIncluded
will not be marshalled back into JSON if no
value was set.
Sample string below:
{
"first_name": "FEAST",
"last_name": "Framework",
"items": [
{
"first_name": "Jeremy",
"last_name": "Presutti"
}
],
"timestamp": "20210405",
"notIncluded": "Feast",
"emptyNotIncluded": "test"
}
Assuming the json string was assigned to $string
, unmarshalling would be performed on the string as follows.
Json::unmarshal($string,TestJsonItem::class);
In addition, calling either of the following would return the JSON string again (in minified format) with notIncluded
not contained in the string, but emptyNotIncluded
will be included since it has a non-empty string value.
$object = Json::unmarshal($string,TestJsonItem::class);
Json::marshal($object);
$object = Json::unmarshal($string,null, new TestJsonItem());
Json::marshal($object);
This string will unmarshal into a class as if the below code had been called manually.
$object = new TestJsonItem();
$object->firstName = 'FEAST';
$object->lastName = 'Framework';
$object->timestamp = Date::createFromFormat('Ymd','20210405');
$object->notIncluded = 'Feast';
$object->emptyNotIncluded = 'test';
$secondaryObject = new TestJsonItem();
$secondaryObject->firstName = 'Jeremy';
$secondaryObject->lastName = 'Presutti';
$object->items = [$secondaryObject];
Note that if the above object is marshalled it will NOT contain the notIncluded
property.
Powered by FEAST Framework
See this project at https://github.com/feastframework/documentation