Skip to content

Tracking "tag" improperly deserialized to an array #23

@tmannherz

Description

@tmannherz

Using v12.0.0 of this package, when you create/update/get a tracking object and deserialize that data using the response object's toArray() method, the "tag" field is improperly deserialized into an array instead of a string.

$client = new \Tracking\Client([
    'apiKey' => 'API KEY',
    'authenticationType' => \Tracking\Config::AUTHENTICATION_TYPE_API_KEY,
]);

$trackingInfo = $client->tracking->getTrackingById('TRACKING ID');
var_dump($trackingInfo->toArray());

This will print something like:

array(75) {
  ["id"]=>
  string(32) "[obfuscated]"
  ["legacy_id"]=>
  string(24) "[obfuscated]"
  ["created_at"]=>
  string(25) "2025-08-01T16:51:26+00:00"
  ["updated_at"]=>
  string(25) "2025-08-01T16:51:29+00:00"
  ["tracking_number"]=>
  string(22) "[obfuscated]"
  ["slug"]=>
  string(4) "usps"
  ["active"]=>
  bool(false)
  ...
  ["source"]=>
  string(3) "api"
  ["tag"]=>
  array(0) {
  }
  ["subtag"]=>
  string(13) "Delivered_001"

Notice how "tag" is an array rather than a string.

It has to do with this line:

    /**
     * @var string|null|\Tracking\Model\Tag Current status of tracking. (
     */
    public $tag;

Since $tag is type-hinted as an object, Symfony will deserialize it into an array. \Tracking\Model\Tag is a class with only constants, and no properties or methods, so it can never represent a track's string tag and should not be included in the type hint.

Furthermore, since Symfony's serializer is used to hydrate the response object, there's no way to pull "tag" from the response.

$client = new \Tracking\Client([
    'apiKey' => 'API KEY',
    'authenticationType' => \Tracking\Config::AUTHENTICATION_TYPE_API_KEY,
]);

$trackingInfo = $client->tracking->getTrackingById('TRACKING ID');
var_dump($trackingInfo->tag);

This yields an empty Tag object with no reference to the actual tag.

object(Tracking\Model\Tag)#3132 (0) {
}

Every response object that type-hints its $tag property needs to be updated as well.

\Tracking\Model\Tag would be more useful if converted to a string-backed enum, in which case it would be properly deserialized:

enum Tag: string
{
    case Pending = 'Pending';
    case InfoReceived = 'InfoReceived';
    case InTransit = 'InTransit';
    case OutForDelivery = 'OutForDelivery';
    case AttemptFail = 'AttemptFail';
    case Delivered = 'Delivered';
    case AvailableForPickup = 'AvailableForPickup';
    case Exception = 'Exception';
    case Expired = 'Expired';
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions