getArrayCopy(); } public function jsonDeserialize(array|string $data): static { if (is_string($data)) { $data = json_decode($data, true); } $this->exchangeArray([]); if (in_array($this->typeValue, $this->primitiveTypes)) { if ($this->associative) { foreach ($data as $key => $value) { $this[$this->normalizeKey($key)] = $value; } } else { foreach ($data as $value) { $this[] = $value; } } } if (!in_array($this->typeValue, $this->primitiveTypes) && is_subclass_of($this->typeValue, \BackedEnum::class)) { if ($this->associative) { foreach ($data as $key => $value) { $this[$this->normalizeKey($key)] = ($this->typeValue)::from($value); } } else { foreach ($data as $value) { $this[] = ($this->typeValue)::from($value); } } } elseif (!in_array($this->typeValue, $this->primitiveTypes) && class_exists($this->typeValue)) { $reflection = new \ReflectionClass($this->typeValue); if ($reflection->implementsInterface(JsonDeserializable::class)) { if ($this->associative) { foreach ($data as $key => $value) { $instance = $reflection->newInstance(); /** @var JsonDeserializable $instance */ $this[$this->normalizeKey($key)] = $instance->jsonDeserialize($value); } } else { foreach ($data as $value) { $instance = $reflection->newInstance(); /** @var JsonDeserializable $instance */ $this[] = $instance->jsonDeserialize($value); } } } } return $this; } /** * JSON round trips turn numeric string keys into integers (and list-shaped * payloads carry integer keys), which a string-keyed collection would * otherwise reject on offsetSet. */ private function normalizeKey(int|string $key): int|string { return $this->typeKey === self::TYPE_STRING ? (string)$key : $key; } }