Skip to content

Commit 2013518

Browse files
committed
Document MixedField.
1 parent a42ba4b commit 2013518

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ All notable changes to `Serde` will be documented in this file.
44

55
Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
66

7+
## 1.4.0 - DATE
8+
9+
### Added
10+
- A new `MixedField` type field is available for use on `mixed` properties. If specified, it allows specifying a preferred object type that an array-ish value will be cast into when deserializing. If the object deserialiation fails, the whole deserialization will fail.
11+
12+
### Deprecated
13+
- Nothing
14+
15+
### Fixed
16+
- Serializing an object that is assigned to a `mixed` field will no longer generate a circular reference error.
17+
18+
### Removed
19+
- Nothing
20+
21+
### Security
22+
- Nothing
23+
724
## 1.3.2 - 2024-12-06
825

926
### Added

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,27 @@ The serialized integer should be read as "this many seconds since the epoc" or "
696696

697697
Note that the permissible range of milliseconds and microseconds is considerably smaller than that for seconds, since there is a limit on the size of an integer that we can represent. For timestamps in the early 21st century there should be no issue, but trying to record the microseconds since the epoc for the setting of Dune (somewhere in the 10,000s) won't work.
698698

699+
### Mixed values
700+
701+
`mixed` values pose an interesting challenge, as their data type is by definition not specified.
702+
703+
On serialization, Serde will make a good faith effort to derive the type to serialize to from the value itself. So if a `mixed` property has a value of `"beep"`, it will try to serialize as a string. If it has a value `[1, 2, 3]`, it will try to serialize as an array.
704+
705+
On deserialization, primitive types (`int`, `float`, `string`) will be read successfully and written to the property. If no additional information is provided, then sequences and dictionaries will also be read into the property as an `array`, but objects are not supported. (They'll be treated like a dictionary.)
706+
707+
Alternatively, you may specify the field as a `#[MixedField(Point::class)]`, which has one required argument, `suggestedType`. If that is specified, any incoming array-ish value will be deserialized to the specified class. If the value is not compatible with that class, an exception will be thrown. That means it is not possible to support both array deserialization and object deserialization at the same time.
708+
709+
```php
710+
class Message
711+
{
712+
public string $message;
713+
#[MixedField(SomeClass::class)]
714+
public mixed $result;
715+
}
716+
```
717+
718+
If you are only ever serializing an object with a `mixed` property, these concerns should not apply and no additional effort should be required.
719+
699720
### Generators, Iterables, and Traversables
700721

701722
PHP has a number of "lazy list" options. Generally, they are all objects that implement the `\Traversable` interface. However, there are several syntax options available with their own subtleties. Serde supports them in different ways.

src/Attributes/MixedField.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@
44

55
namespace Crell\Serde\Attributes;
66

7+
use Attribute;
78
use Crell\AttributeUtils\SupportsScopes;
89
use Crell\Serde\TypeField;
9-
use Attribute;
1010

11+
/**
12+
* Specifies how a mixed field should be deserialized.
13+
*
14+
* In particular, it allows specifying a class type to which an array-ish
15+
* value should be deserialized.
16+
*/
1117
#[Attribute(Attribute::TARGET_PROPERTY)]
1218
class MixedField implements TypeField, SupportsScopes
1319
{
20+
/**
21+
* @param string $suggestedType
22+
* The class name that an array-ish value should be deserialized into.
23+
* Primitive values will be left as is when deserializing.
24+
* @param array<string|null> $scopes
25+
* The scopes in which this attribute should apply.
26+
*/
1427
public function __construct(
1528
public readonly string $suggestedType,
1629
protected readonly array $scopes = [null],

src/PropertyHandler/MixedExporter.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
* Exporter/importer for `mixed` properties.
2121
*
2222
* This class makes a good-faith attempt to detect the type of a given field by its value.
23-
* It currently does not work for objects, and on import it works only on array-based
24-
* formats (JSON, YAML, TOML, etc.)
23+
* On import, it currently works only on array-based formats (JSON, YAML, TOML, etc.)
24+
*
25+
* To deserialize into an object, the property must have the MixedField attribute.
26+
*
27+
* @see MixedField
2528
*/
2629
class MixedExporter implements Importer, Exporter
2730
{

0 commit comments

Comments
 (0)