Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .fernignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Specify files that shouldn't be modified by Fern
LICENSE.md
CONTRIBUTING.md

# nullable DateTime fix
src/Core/Json/JsonSerializableType.php
src/Types/PushPayLinkRequest.php
tests/Core/Json/NullPropertyTest.php
17 changes: 12 additions & 5 deletions src/Core/Json/JsonSerializableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public function toJson(): string
}

/**
* Serializes the object to an array.
* Serializes the object to a JSON-ready value.
*
* @return mixed[] Array representation of the object.
* @return array<string,mixed>|\stdClass
* @throws JsonException If serialization fails.
*/
public function jsonSerialize(): array
public function jsonSerialize(): array|\stdClass
{
$result = [];
$reflectionClass = new \ReflectionClass($this);
Expand All @@ -65,21 +65,24 @@ public function jsonSerialize(): array
}

// Handle Union annotations
$alreadySerialized = false;
$unionTypeAttr = $property->getAttributes(Union::class)[0] ?? null;
if ($unionTypeAttr) {
$unionType = $unionTypeAttr->newInstance();
$value = JsonSerializer::serializeUnion($value, $unionType);
$alreadySerialized = true;
}

// Handle arrays with type annotations
$arrayTypeAttr = $property->getAttributes(ArrayType::class)[0] ?? null;
if ($arrayTypeAttr && is_array($value)) {
if (!$alreadySerialized && $arrayTypeAttr && is_array($value)) {
$arrayType = $arrayTypeAttr->newInstance()->type;
$value = JsonSerializer::serializeArray($value, $arrayType);
$alreadySerialized = true;
}

// Handle object
if (is_object($value)) {
if (!$alreadySerialized && is_object($value)) {
$value = JsonSerializer::serializeObject($value);
}

Expand All @@ -88,6 +91,10 @@ public function jsonSerialize(): array
$result[$jsonKey] = $value;
}
}
// Empty object models must serialize to {} (not [])
if ($result === []) {
return new \stdClass();
}
return $result;
}

Expand Down
24 changes: 19 additions & 5 deletions src/Types/PushPayLinkRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,22 @@ public function jsonSerialize(): array
$result['channel'] = $this->channel;

$base = parent::jsonSerialize();
$result = array_merge($base, $result);
if (is_array($base)) {
$result = array_merge($base, $result);
}

switch ($this->channel) {
case 'email':
$value = $this->asEmail()->jsonSerialize();
$result = array_merge($value, $result);
if (is_array($value)) {
$result = array_merge($value, $result);
}
break;
case 'sms':
$value = $this->asSms()->jsonSerialize();
$result = array_merge($value, $result);
if (is_array($value)) {
$result = array_merge($value, $result);
}
break;
case '_unknown':
default:
Expand All @@ -152,9 +158,15 @@ public function jsonSerialize(): array
}
if ($this->value instanceof JsonSerializableType) {
$value = $this->value->jsonSerialize();
$result = array_merge($value, $result);
if (is_array($value)) {
$result = array_merge($value, $result);
}
} elseif (is_array($this->value)) {
$result = array_merge($this->value, $result);
} elseif ($this->value instanceof \stdClass) {
/** @var array<string, mixed> $normalized */
$normalized = (array) $this->value;
$result = array_merge($normalized, $result);
}
}

Expand Down Expand Up @@ -190,7 +202,9 @@ public static function jsonDeserialize(array $data): static
case '_unknown':
default:
$args['channel'] = '_unknown';
$args['value'] = $data;
/** @var array<string, mixed> $unknown */
$unknown = $data;
$args['value'] = $unknown;
}

// @phpstan-ignore-next-line
Expand Down
1 change: 1 addition & 0 deletions tests/Core/Json/NullPropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function testNullPropertiesAreOmitted(): void
);

$serialized = $object->jsonSerialize();
$this->assertIsArray($serialized, 'Serialized result should be an array.');
$this->assertArrayHasKey('non_null_property', $serialized, 'non_null_property should be present in the serialized JSON.');
$this->assertArrayNotHasKey('null_property', $serialized, 'null_property should be omitted from the serialized JSON.');
$this->assertEquals('Test String', $serialized['non_null_property'], 'non_null_property should have the correct value.');
Expand Down
Loading