Add pjson support
This commit is contained in:
parent
50854275a8
commit
478684621c
|
@ -23,7 +23,8 @@
|
||||||
"phpoption/phpoption": "^1.9"
|
"phpoption/phpoption": "^1.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^11"
|
"phpunit/phpunit": "^11",
|
||||||
|
"square/pjson": "^0.5.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
"Test\\": "./tests",
|
||||||
"Test\\Unit\\": "./tests/unit",
|
"Test\\Unit\\": "./tests/unit",
|
||||||
"Test\\Integration\\": "./tests/integration",
|
"Test\\Integration\\": "./tests/integration",
|
||||||
"Test\\Integration\\PostgreSQL\\": "./tests/integration/postgresql",
|
"Test\\Integration\\PostgreSQL\\": "./tests/integration/postgresql",
|
||||||
|
|
62
composer.lock
generated
62
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "71593fca8aa32b0cd963eb52bad1a34e",
|
"content-hash": "dc897c0ab21d662a65b3818331edd2f2",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "netresearch/jsonmapper",
|
"name": "netresearch/jsonmapper",
|
||||||
|
@ -372,16 +372,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
"version": "11.0.3",
|
"version": "11.0.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||||
"reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92"
|
"reference": "4dc2b7a606073f0fb80da09842ffb068b627c38f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e35a2cbcabac0e6865fd373742ea432a3c34f92",
|
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4dc2b7a606073f0fb80da09842ffb068b627c38f",
|
||||||
"reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92",
|
"reference": "4dc2b7a606073f0fb80da09842ffb068b627c38f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -438,7 +438,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.3"
|
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.4"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -446,7 +446,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-12T15:35:40+00:00"
|
"time": "2024-06-29T08:26:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-file-iterator",
|
"name": "phpunit/php-file-iterator",
|
||||||
|
@ -1716,6 +1716,54 @@
|
||||||
],
|
],
|
||||||
"time": "2024-02-02T06:10:47+00:00"
|
"time": "2024-02-02T06:10:47+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "square/pjson",
|
||||||
|
"version": "v0.5.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/square/pjson.git",
|
||||||
|
"reference": "cf9f9a7810ad7287b30658f60c0bbbba80217319"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/square/pjson/zipball/cf9f9a7810ad7287b30658f60c0bbbba80217319",
|
||||||
|
"reference": "cf9f9a7810ad7287b30658f60c0bbbba80217319",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"orchestra/testbench": "^7.11",
|
||||||
|
"phpstan/phpstan": "^1.8",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"squizlabs/php_codesniffer": "^3.7",
|
||||||
|
"symfony/var-dumper": "^6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Square\\Pjson\\": "src/",
|
||||||
|
"Square\\Pjson\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"Apache-2.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Seb",
|
||||||
|
"email": "sebastien@squareup.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Library for JSON <=> PHP model serialization / deserialization. Deserialize JSON directly into your object model PHP classes.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/square/pjson/issues",
|
||||||
|
"source": "https://github.com/square/pjson/tree/v0.5.0"
|
||||||
|
},
|
||||||
|
"time": "2024-03-15T18:19:22+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
namespace BitBadger\PDODocument\Mapper;
|
namespace BitBadger\PDODocument\Mapper;
|
||||||
|
|
||||||
use BitBadger\PDODocument\DocumentException;
|
use BitBadger\PDODocument\DocumentException;
|
||||||
|
use Exception;
|
||||||
use JsonMapper;
|
use JsonMapper;
|
||||||
use JsonMapper_Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map domain class instances from JSON documents
|
* Map domain class instances from JSON documents
|
||||||
|
@ -32,12 +32,15 @@ class DocumentMapper implements Mapper
|
||||||
public function map(array $result): mixed
|
public function map(array $result): mixed
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
if (method_exists($this->className, 'fromJsonString')) {
|
||||||
|
return $this->className::fromJsonString($result[$this->fieldName]);
|
||||||
|
}
|
||||||
$json = json_decode($result[$this->fieldName]);
|
$json = json_decode($result[$this->fieldName]);
|
||||||
if (is_null($json)) {
|
if (is_null($json)) {
|
||||||
throw new DocumentException("Could not map document for $this->className: " . json_last_error_msg());
|
throw new DocumentException("Could not map document for $this->className: " . json_last_error_msg());
|
||||||
}
|
}
|
||||||
return (new JsonMapper())->map($json, $this->className);
|
return (new JsonMapper())->map($json, $this->className);
|
||||||
} catch (JsonMapper_Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
throw new DocumentException("Could not map document for $this->className", previous: $ex);
|
throw new DocumentException("Could not map document for $this->className", previous: $ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,10 @@ class Parameters
|
||||||
*/
|
*/
|
||||||
public static function json(string $name, object|array $document): array
|
public static function json(string $name, object|array $document): array
|
||||||
{
|
{
|
||||||
return [$name => json_encode($document, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)];
|
return [$name => match (is_object($document) && method_exists($document, 'toJson')) {
|
||||||
|
true => $document->toJson(),
|
||||||
|
false => json_encode($document, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
16
tests/PjsonDocument.php
Normal file
16
tests/PjsonDocument.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Test;
|
||||||
|
|
||||||
|
use Square\Pjson\{Json, JsonSerialize};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test document annotated with pjson attributes using the `JsonSerialize` trait
|
||||||
|
*/
|
||||||
|
class PjsonDocument
|
||||||
|
{
|
||||||
|
use JsonSerialize;
|
||||||
|
|
||||||
|
public function __construct(#[Json] public PjsonId $id = new PjsonId(''), #[Json] public string $name = '',
|
||||||
|
#[Json('num_value')] public int $numValue = 0, public string $skipped = 'yep') { }
|
||||||
|
}
|
23
tests/PjsonId.php
Normal file
23
tests/PjsonId.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Test;
|
||||||
|
|
||||||
|
use Square\Pjson\JsonDataSerializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serializable ID wrapper class
|
||||||
|
*/
|
||||||
|
class PjsonId implements JsonDataSerializable
|
||||||
|
{
|
||||||
|
public function __construct(protected string $value) { }
|
||||||
|
|
||||||
|
public function toJsonData(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromJsonData($jd, array|string $path = []): static
|
||||||
|
{
|
||||||
|
return new static($jd);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use BitBadger\PDODocument\{DocumentException, Field};
|
||||||
use BitBadger\PDODocument\Mapper\DocumentMapper;
|
use BitBadger\PDODocument\Mapper\DocumentMapper;
|
||||||
use PHPUnit\Framework\Attributes\TestDox;
|
use PHPUnit\Framework\Attributes\TestDox;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Test\{PjsonDocument, PjsonId};
|
||||||
|
|
||||||
// ** Test class hierarchy for serialization **
|
// ** Test class hierarchy for serialization **
|
||||||
|
|
||||||
|
@ -48,10 +49,28 @@ class DocumentMapperTest extends TestCase
|
||||||
$this->assertEquals('tester', $doc->subDoc->name, 'Sub-document name not filled correctly');
|
$this->assertEquals('tester', $doc->subDoc->name, 'Sub-document name not filled correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[TestDox('Map succeeds with valid JSON for pjson class')]
|
||||||
|
public function testMapSucceedsWithValidJSONForPjsonClass(): void
|
||||||
|
{
|
||||||
|
$doc = (new DocumentMapper(PjsonDocument::class))->map(['data' => '{"id":"seven","name":"bob","num_value":8}']);
|
||||||
|
$this->assertNotNull($doc, 'The document should not have been null');
|
||||||
|
$this->assertEquals(new PjsonId('seven'), $doc->id, 'ID not filled correctly');
|
||||||
|
$this->assertEquals('bob', $doc->name, 'Name not filled correctly');
|
||||||
|
$this->assertEquals(8, $doc->numValue, 'Numeric value not filled correctly');
|
||||||
|
$this->assertFalse(isset($doc->skipped), 'Non-JSON field has not been set');
|
||||||
|
}
|
||||||
|
|
||||||
#[TestDox('Map fails with invalid JSON')]
|
#[TestDox('Map fails with invalid JSON')]
|
||||||
public function testMapFailsWithInvalidJSON(): void
|
public function testMapFailsWithInvalidJSON(): void
|
||||||
{
|
{
|
||||||
$this->expectException(DocumentException::class);
|
$this->expectException(DocumentException::class);
|
||||||
(new DocumentMapper(TestDocument::class))->map(['data' => 'this is not valid']);
|
(new DocumentMapper(TestDocument::class))->map(['data' => 'this is not valid']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[TestDox('Map fails with invalid JSON for pjson class')]
|
||||||
|
public function testMapFailsWithInvalidJSONForPjsonClass(): void
|
||||||
|
{
|
||||||
|
$this->expectException(DocumentException::class);
|
||||||
|
(new DocumentMapper(PjsonDocument::class))->map(['data' => 'not even close']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace Test\Unit;
|
||||||
use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters};
|
use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters};
|
||||||
use PHPUnit\Framework\Attributes\TestDox;
|
use PHPUnit\Framework\Attributes\TestDox;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use stdClass;
|
||||||
|
use Test\{PjsonDocument, PjsonId};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the Parameters class
|
* Unit tests for the Parameters class
|
||||||
|
@ -24,13 +26,31 @@ class ParametersTest extends TestCase
|
||||||
$this->assertEquals([':id' => '7'], Parameters::id(7), 'ID parameter not constructed correctly');
|
$this->assertEquals([':id' => '7'], Parameters::id(7), 'ID parameter not constructed correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testJsonSucceeds(): void
|
public function testJsonSucceedsForArray(): void
|
||||||
{
|
{
|
||||||
$this->assertEquals([':it' => '{"id":18,"url":"https://www.unittest.com"}'],
|
$this->assertEquals([':it' => '{"id":18,"url":"https://www.unittest.com"}'],
|
||||||
Parameters::json(':it', ['id' => 18, 'url' => 'https://www.unittest.com']),
|
Parameters::json(':it', ['id' => 18, 'url' => 'https://www.unittest.com']),
|
||||||
'JSON parameter not constructed correctly');
|
'JSON parameter not constructed correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[TestDox('json succeeds for stdClass')]
|
||||||
|
public function testJsonSucceedsForStdClass(): void
|
||||||
|
{
|
||||||
|
$obj = new stdClass();
|
||||||
|
$obj->id = 19;
|
||||||
|
$obj->url = 'https://testhere.info';
|
||||||
|
$this->assertEquals([':it' => '{"id":19,"url":"https://testhere.info"}'], Parameters::json(':it', $obj),
|
||||||
|
'JSON parameter not constructed correctly');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testJsonSucceedsForPjsonClass(): void
|
||||||
|
{
|
||||||
|
$this->assertEquals([':it' => '{"id":"999","name":"a test","num_value":98}'],
|
||||||
|
Parameters::json(':it', new PjsonDocument(new PjsonId('999'), 'a test', 98, 'nothing')),
|
||||||
|
'JSON parameter not constructed correctly');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testNameFieldsSucceeds(): void
|
public function testNameFieldsSucceeds(): void
|
||||||
{
|
{
|
||||||
$named = Parameters::nameFields([Field::EQ('it', 17), Field::EQ('also', 22, ':also'), Field::EQ('other', 24)]);
|
$named = Parameters::nameFields([Field::EQ('it', 17), Field::EQ('also', 22, ':also'), Field::EQ('other', 24)]);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user