Skip to content

Commit

Permalink
new Setting: Skip Inherited Properties
Browse files Browse the repository at this point in the history
  • Loading branch information
peterGdot committed Aug 20, 2024
1 parent 7b57224 commit cab09f1
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 18 deletions.
8 changes: 4 additions & 4 deletions demos/Models/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
class Order
{
#[Json("Id")]
public int $id2;
public int $id2 = 0;

public string|int|null $externId;
public string|int|null $externId = null;

/**
* @var string
*/
public $channel;
public $channel = "Demo Channel";

#[JsonIgnore(true, true)]
public string $ignore;
Expand All @@ -24,5 +24,5 @@ class Order
#[JsonType(OrderItem::class)]
public array $items = [];

public OrderItem $primaryItem;
public ?OrderItem $primaryItem = null;
}
9 changes: 9 additions & 0 deletions demos/Models/SpecialOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace Demo\Models;

class SpecialOrder extends Order {

public string $special = "Special";

public \DateTime $dateTime;
}
51 changes: 51 additions & 0 deletions demos/settings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
namespace Demo;

use Demo\Models\SpecialOrder;
use Pyther\Json\Exceptions\JsonException;
use Pyther\Json\Json;
use Pyther\Json\JsonSettings;
use Pyther\Json\NamingPolicies\CamelToPascalNamingPolicy;
use Pyther\Json\Types\EnumFormat;

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
header("Content-Type: text/plain");

$autoloader = require_once __DIR__."/../vendor/autoload.php";
$autoloader->addPsr4('Demo\\', __DIR__);

try {
$order = new SpecialOrder();
$order->dateTime = new \DateTime();

$order = [ $order, $order];
// serialize with default settings
$json = Json::serialize($order);
echo "\n\nJSON without settings:\n";
echo $json;

// serialize with custom settings
$settings = new JsonSettings();
$settings->setNamingPolicy(new CamelToPascalNamingPolicy());
$settings->setDateTimeAsString(false);
$settings->setSkipNull(true);
$settings->setSkipEmptyArray(true);
$json = Json::serialize($order, $settings);

echo "\n\nJSON with settings 1:\n";
echo $json;

// serialize with custom settings
$settings->setSkipInheritedProperties(true);
$json = Json::serialize($order, $settings);

echo "\n\nJSON with settings 2:\n";
echo $json;

} catch (JsonException $ex) {
echo $ex->getMessage();
} catch (\Exception $ex) {
echo "Internal Error: ".$ex->getMessage();
}
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ A lightweight (de)serializer between json strings and data models with the follo
- include protected properties
- skip null values
- skip empty arrays
- enum format
- skip inherited properties
- enum format (name, value or full)
- and more ...
- takes documentation "@var" hints into account
- no external dependencies
Expand Down
7 changes: 6 additions & 1 deletion src/JsonDeserializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ private function fillObject(object $object, array $data): ?object
// if no data available => skip;
if (!isset($data[$jsonName])) continue;

// skip inherited properties?
if ($this->settings->getSkipInheritedProperties() && $prop->getDeclaringClass()->getName() != $reflObject->getName()) continue;

// gather type informations
$typeInfo = new TypeInfo($prop);

Expand Down Expand Up @@ -145,7 +148,9 @@ private function fillObject(object $object, array $data): ?object
* @param string|null $ns The optional $ns if the full qualified was'n found.
* @return object Returns a new instance of the object, on success.
*/
private static function createObject(string $fqn, ?string $ns = null): object {
private static function createObject(string $fqn, ?string $ns = null): object
{
$fqn = str_replace("|null", "", $fqn);
if (!class_exists($fqn) ) {
if ($ns === null) {
throw new JsonException("Class '$fqn' not found!");
Expand Down
22 changes: 14 additions & 8 deletions src/JsonSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@ private function serializeObject(object $object): ?array

$value = $this->getValue($object, $prop);

// skip properties with null values
if ($value === null && $this->settings->getSkipNull()) continue;

// skip inherited properties?
if ($this->settings->getSkipInheritedProperties() && $prop->getDeclaringClass()->getName() != $reflObject->getName()) continue;

if ($value === null) {
$data[$jsonName] = null;
}
Expand All @@ -77,10 +81,14 @@ private function serializeObject(object $object): ?array
}
// b) special case: DateTime
else if ($typeInfo->type == "DateTime") {
$dateTimeMetaFormat = Meta::getPropertyMetaArguments($prop, JsonDateTime::class);
$format = $dateTimeMetaFormat !== null ? $dateTimeMetaFormat[0] : $this->settings->getDateTimeFormat();
$dateTimeFormated = $value->format($format);
$data[$jsonName] = $dateTimeFormated;
if ($this->settings->getDateTimeAsString()) {
$dateTimeMetaFormat = Meta::getPropertyMetaArguments($prop, JsonDateTime::class);
$format = $dateTimeMetaFormat !== null ? $dateTimeMetaFormat[0] : $this->settings->getDateTimeFormat();
$dateTimeFormated = $value->format($format);
$data[$jsonName] = $dateTimeFormated;
} else {
$data[$jsonName] = $value;
}
}
// c) special case: enum
else if ($typeInfo->type !== null && enum_exists($typeInfo->type))
Expand All @@ -107,13 +115,11 @@ private function serializeObject(object $object): ?array
*/
private function serializeArray(array $array): ?array
{
$settings = $this->settings;

$data = [];
foreach ($array as $item) {
if ($item instanceof \Datetime) {
if ($settings->getDateTimeAsString()) {
$dateTimeFormated = $item->format($settings->getDateTimeFormat());
if ($this->settings->getDateTimeAsString()) {
$dateTimeFormated = $item->format($this->settings->getDateTimeFormat());
$data[] = $dateTimeFormated;
} else {
$data[] = $item;
Expand Down
23 changes: 19 additions & 4 deletions src/JsonSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ class JsonSettings
{
// flags
private const INCLUDE_PROTECTED_FLAG = 1;
private const SKIP_INHERITED_PROPERTIES = 2;
// on serialization only
private const USE_PRETTY_PRINT = 2;
private const DATETIME_AS_STRING = 4;
private const SKIP_NULL = 8;
private const SKIP_EMPTY_ARRAY = 16;
private const USE_PRETTY_PRINT = 4;
private const DATETIME_AS_STRING = 8;
private const SKIP_NULL = 16;
private const SKIP_EMPTY_ARRAY = 32;

private int $flags = self::USE_PRETTY_PRINT | self::DATETIME_AS_STRING;
private ?BaseNamingPolicy $namingPolicy = null;
Expand Down Expand Up @@ -69,6 +70,20 @@ public function getDateTimeFormat(): string {
return $this->dataTimeFormat;
}

/**
* Define to skip ingerited properties (false by default).
* @param boolean $value
* @return static
*/
public function setSkipInheritedProperties(bool $value = true): static {
$this->flags = $value ? $this->flags | self::SKIP_INHERITED_PROPERTIES : $this->flags & ~self::SKIP_INHERITED_PROPERTIES;
return $this;
}

public function getSkipInheritedProperties(): bool {
return ($this->flags & self::SKIP_INHERITED_PROPERTIES) != 0;
}

#region on serialization only

/**
Expand Down

0 comments on commit cab09f1

Please sign in to comment.