* @license MIT */ declare(strict_types=1); namespace BitBadger\PDODocument\Mapper; use BitBadger\PDODocument\DocumentException; use Exception; use JsonMapper; /** * Map domain class instances from JSON documents * * @template TDoc The type of document returned by this mapper * @implements Mapper Provide a mapping from JSON */ class DocumentMapper implements Mapper { /** * Constructor * * @param class-string $className The type of class to be returned by this mapping * @param string $fieldName The name of the field (optional; defaults to `data`) */ public function __construct(public string $className, public string $fieldName = 'data') {} /** * Map a result to a domain class instance * * @param array $result An associative array representing a single database result * @return TDoc The document, deserialized from its JSON representation * @throws DocumentException If the JSON cannot be deserialized */ public function map(array $result): mixed { try { if (method_exists($this->className, 'fromJsonString')) { return $this->className::fromJsonString($result[$this->fieldName]); } $json = json_decode($result[$this->fieldName]); if (is_null($json)) { throw new DocumentException("Could not map document for $this->className: " . json_last_error_msg()); } return (new JsonMapper())->map($json, $this->className); } catch (Exception $ex) { throw new DocumentException("Could not map document for $this->className", previous: $ex); } } }