From 2b0e878286acda8ae4ec0a07d0b5b87af17d14ce Mon Sep 17 00:00:00 2001 From: Julian Gojani Date: Sun, 10 Oct 2021 16:25:05 +0200 Subject: [PATCH] Added #[ArrayType(type)] and changed README --- README.md | 117 ++++++++++++------ composer.json | 2 +- src/main/de/interaapps/jsonplus/JSONPlus.php | 25 +++- .../jsonplus/attributes/ArrayType.php | 17 +++ .../jsonplus/typemapper/ArrayTypeMapper.php | 27 ++++ .../jsonplus/typemapper/ObjectTypeMapper.php | 35 +++++- src/test/testbootstrap.php | 32 ++++- uppm.json | 2 +- 8 files changed, 211 insertions(+), 46 deletions(-) create mode 100644 src/main/de/interaapps/jsonplus/attributes/ArrayType.php create mode 100644 src/main/de/interaapps/jsonplus/typemapper/ArrayTypeMapper.php diff --git a/README.md b/README.md index 23c660d..fbe1878 100644 --- a/README.md +++ b/README.md @@ -2,58 +2,99 @@ ## Getting started +### JSONPlus instance ```php fromJson('{"obj": "hello world"}'); +echo $obj->string; // -> hello world + +// Enabling pretty printing +$jsonPlus->setPrettyPrinting(true); + +echo $jsonPlus->toJson($obj); // -> {"obj": "hello world"} + +/// Other drivers +// Default if json_decode exists in JSONPlus::createDefault() +$jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter()); +// Custom JSON implementation +$jsonPlus = new JSONPlus(new JsonSerializationAdapter()); +``` + +### Model +```php +first_name.", I have the ID ".$user->id + ."and I'm in the organisation ".$user->organisation->name."\n"; + +foreach ($user->friends as $friend) { + echo "One of my friends: ".$friend->name."\n"; +} -echo $test->toJson(); +// Encoding to JSON +echo $user->toJson(); -// Custom JSONPlus Instance +// Decode typed JSON-array $jsonPlus = JSONPlus::createDefault(); -// $jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter()); -$arrJson = $jsonPlus->toJson([ - "A", "B", "C" -]); -echo $arrJson; -// '["A", "B", "C"]' - -echo $jsonPlus->fromJson($arrJson)[0]; -// "A" - -// Setting JSONModal -Test::setJsonPlusInstance($jsonPlus); -// For all (Default instance) -JSONPlus::$default = $jsonPlus; - -/// Using other JSON-Drivers -// Uses PHPs default json_encode and json_decode methods -$jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter()); -// Uses an custom implementation of JSON. This will be automatically chosen by JSONPlus::createDefault when json_decode doesn't exist -$jsonPlus = new JSONPlus(new JsonSerializationAdapter()); +$users = $jsonPlus->fromMappedArrayJson('[...]', User::class); +foreach ($users as $user) {} +``` +`Tip`: If you are using PHPStorm or any other intelligent IDE you might add PHP-Docs to some fields. + +For Typed Arrays: +```php +/** +* @var array +*/ ``` ## Installation diff --git a/composer.json b/composer.json index ee48514..7b97d79 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "interaapps/jsonplus", - "version": "1.0.2", + "version": "1.0.3", "type": "library", "authors": [ { diff --git a/src/main/de/interaapps/jsonplus/JSONPlus.php b/src/main/de/interaapps/jsonplus/JSONPlus.php index d28457a..8db0e04 100644 --- a/src/main/de/interaapps/jsonplus/JSONPlus.php +++ b/src/main/de/interaapps/jsonplus/JSONPlus.php @@ -4,6 +4,7 @@ use de\interaapps\jsonplus\serializationadapter\impl\JsonSerializationAdapter; use de\interaapps\jsonplus\serializationadapter\impl\phpjson\PHPJsonSerializationAdapter; use de\interaapps\jsonplus\serializationadapter\SerializationAdapter; +use de\interaapps\jsonplus\typemapper\ArrayTypeMapper; use de\interaapps\jsonplus\typemapper\ObjectTypeMapper; use de\interaapps\jsonplus\typemapper\PassThroughTypeMapper; use de\interaapps\jsonplus\typemapper\StdClassObjectTypeMapper; @@ -29,7 +30,7 @@ public function __construct( "int" => $this->passThroughTypeMapper, "double" => $this->passThroughTypeMapper, "bool" => $this->passThroughTypeMapper, - "array" => $this->passThroughTypeMapper, + "array" => new ArrayTypeMapper($this), "boolean" => $this->passThroughTypeMapper, "NULL" => $this->passThroughTypeMapper, "stdClass" => new StdClassObjectTypeMapper($this), @@ -46,6 +47,28 @@ public function fromJson(string $json, string|null $type = null){ return $this->map($this->serializationAdapter->fromJson($json), $type); } + /** + * @template T + * @param string $json The input json + * @param class-string $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically) + * @return array + * */ + public function fromMappedArrayJson(string $json, string $type) : array { + return $this->mapTypedArray($this->serializationAdapter->fromJson($json), $type); + } + /** + * @template T + * @param array $arr + * @param class-string $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically) + * @return array + * */ + public function mapTypedArray(array $arr, string $type) : array { + $out = []; + foreach ($arr as $i=>$v) + $out[$i] = $this->map($v, $type); + return $out; + } + /** * @template T * @param $o diff --git a/src/main/de/interaapps/jsonplus/attributes/ArrayType.php b/src/main/de/interaapps/jsonplus/attributes/ArrayType.php new file mode 100644 index 0000000..0b8cb6f --- /dev/null +++ b/src/main/de/interaapps/jsonplus/attributes/ArrayType.php @@ -0,0 +1,17 @@ +jsonPlus->mapTypedArray($o, $entriesType); + } else + return $o; + } + + public function mapToJson(mixed $o, string $type): mixed { + $out = []; + foreach ($o as $i=>$val) { + $out[$i] = $this->jsonPlus->mapToJson($val); + } + return $out; + } +} \ No newline at end of file diff --git a/src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php b/src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php index 54c4991..49f2336 100644 --- a/src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php +++ b/src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php @@ -2,6 +2,7 @@ namespace de\interaapps\jsonplus\typemapper; +use de\interaapps\jsonplus\attributes\ArrayType; use de\interaapps\jsonplus\attributes\Serialize; use de\interaapps\jsonplus\JSONPlus; use ReflectionClass; @@ -30,8 +31,18 @@ public function map(mixed $o, string $type): mixed { continue 2; } - if ($o != null && isset($o->{$name})) + if ($o != null && isset($o->{$name})) { + // Mapping Array if #[ArrayType] is given + if (is_array($o->{$name})) { + $arrayTypeAttribs = $property->getAttributes(ArrayType::class); + foreach ($arrayTypeAttribs as $attrib) { + $property->setValue($oo, $this->jsonPlus->mapTypedArray($o->{$name}, $attrib->newInstance()->value)); + continue 2; + } + } + $property->setValue($oo, $this->jsonPlus->map($o?->{$name}, strval($property->getType()))); + } } } @@ -46,6 +57,7 @@ public function mapToJson(mixed $o, string $type): mixed { foreach ($class->getProperties() as $property) { if (!$property->isStatic()) { $name = $property?->getName(); + $overrideName = $property?->getName(); $serializeAttribs = $property->getAttributes(Serialize::class); foreach ($serializeAttribs as $attrib) { @@ -55,8 +67,27 @@ public function mapToJson(mixed $o, string $type): mixed { continue 2; } - if ($o != null && isset($o->{$name})) + + if ($o !== null && isset($o->{$name})) { + // Mapping Array if #[ArrayType] is given + if (is_array($o->{$name})) { + $outArr = []; + foreach ($o->{$name} as $i=>$entry) + $outArr[$i] = $this->jsonPlus->mapToJson($entry); + $oo[$overrideName] = $outArr; + continue; + } + + // Mapping Type + if (gettype($o?->{$name}) == "object") { + $class = get_class($o?->{$name}); + if ($class != "stdClass") { + $oo[$overrideName] = $this->mapToJson($o?->{$name}, $class); + continue; + } + } $oo[$overrideName] = $o?->{$name}; + } } } return (object) $oo; diff --git a/src/test/testbootstrap.php b/src/test/testbootstrap.php index 55f661d..4f7d4c9 100644 --- a/src/test/testbootstrap.php +++ b/src/test/testbootstrap.php @@ -1,6 +1,7 @@ toJson(); +echo Test::fromJson(JSON)->toJson(); $json = new JSONPlus(new JsonSerializationAdapter()); $var = $json->fromJson(JSON, Test::class); echo $var->name."\n"; -echo $json->toJson($var); \ No newline at end of file +echo $json->toJson($var); + + +class Test3 { + use JSONModel; + + /** + * @var array + */ + #[ArrayType(Test2::class)] + public array $myArray; +} +$arr = $json->fromMappedArrayJson('[ + { + "shush": "yipi" + }, + { + "shush": "yipu" + } +]', Test2::class); + +foreach ($arr as $val) { + echo $val->sheesh; +} + diff --git a/uppm.json b/uppm.json index 66c2762..a519eee 100644 --- a/uppm.json +++ b/uppm.json @@ -1,6 +1,6 @@ { "name": "interaapps/jsonplus", - "version": "1.0.2", + "version": "1.0.3", "phpVersion": ">8.0", "repositories": [], "run": {