Skip to content

Commit

Permalink
Added #[ArrayType(type)] and changed README
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianFun123 committed Oct 10, 2021
1 parent 36a81fa commit 2b0e878
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 46 deletions.
117 changes: 79 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,99 @@

## Getting started

### JSONPlus instance
```php
<?php
use de\interaapps\jsonplus\JSONPlus;
use de\interaapps\jsonplus\serializationadapter\impl\JsonSerializationAdapter;
use de\interaapps\jsonplus\serializationadapter\impl\phpjson\PHPJsonSerializationAdapter;

$jsonPlus = JSONPlus::createDefault();
$obj = $jsonPlus->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
<?php
use de\interaapps\jsonplus\JSONPlus;
use de\interaapps\jsonplus\JSONModel;
use de\interaapps\jsonplus\attributes\Serialize;
use de\interaapps\jsonplus\JSONModel;use de\interaapps\jsonplus\JSONPlus;use de\interaapps\jsonplus\serializationadapter\impl\JsonSerializationAdapter;use de\interaapps\jsonplus\serializationadapter\impl\phpjson\PHPJsonSerializationAdapter;
use de\interaapps\jsonplus\attributes\ArrayType;

class Test2 {
use JSONModel;

#[Serialize("my_array")]
public array $myArray;
class Organisation {
public string $name;
}

class Test {
// Adds the Test#toJson and Test::fromJson functions
class User {
use JSONModel;

public string $test;
public Test2 $test2;
public int id;

#[Serialize("firstName")]
public string firstName;

#[Serialize(hidden: true)]
public string password;

public ?Organisation $organisation;

// Set Type for array:
#[ArrayType(User::class)]
public array $friends;
}

$test = Test::fromJson('{
"test": "Hello World",
"test2": {
"my_array": ["Hello There"]
}
}');
$json = '{
"id": 12343,
"first_name": "Jeff",
"organisation": {
"name": "InteraApps"
},
"friends": [
{
"id": 3245,
"first_name": "John",
"friends": []
}
]
}';

// Decoding the JSON
$user = User::fromJson($json);

echo "Hello. My name is ".$user->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<User>
*/
```

## Installation
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "interaapps/jsonplus",
"version": "1.0.2",
"version": "1.0.3",
"type": "library",
"authors": [
{
Expand Down
25 changes: 24 additions & 1 deletion src/main/de/interaapps/jsonplus/JSONPlus.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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),
Expand All @@ -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<T> $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically)
* @return array<T>
* */
public function fromMappedArrayJson(string $json, string $type) : array {
return $this->mapTypedArray($this->serializationAdapter->fromJson($json), $type);
}
/**
* @template T
* @param array $arr
* @param class-string<T> $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically)
* @return array<T>
* */
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
Expand Down
17 changes: 17 additions & 0 deletions src/main/de/interaapps/jsonplus/attributes/ArrayType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace de\interaapps\jsonplus\attributes;

use Attribute;

#[Attribute]
class ArrayType {
/**
* @param class-string $value
*/
public function __construct(
public string $value
){
}

}
27 changes: 27 additions & 0 deletions src/main/de/interaapps/jsonplus/typemapper/ArrayTypeMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
namespace de\interaapps\jsonplus\typemapper;


use de\interaapps\jsonplus\JSONPlus;

class ArrayTypeMapper implements TypeMapper {
public function __construct(
private JSONPlus $jsonPlus
){
}

public function map(mixed $o, string $type, $entriesType = null): mixed {
if ($entriesType !== null) {
return $this->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;
}
}
35 changes: 33 additions & 2 deletions src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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())));
}
}
}

Expand All @@ -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) {
Expand All @@ -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;
Expand Down
32 changes: 29 additions & 3 deletions src/test/testbootstrap.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
// Init

use de\interaapps\jsonplus\attributes\ArrayType;
use de\interaapps\jsonplus\attributes\Serialize;
use de\interaapps\jsonplus\JSONModel;
use de\interaapps\jsonplus\JSONPlus;
Expand All @@ -17,6 +18,7 @@
echo "Testing:\n";

class Test2 {
#[Serialize("shush")]
public string $sheesh;
}

Expand Down Expand Up @@ -47,14 +49,38 @@ public function setName(string $name): Test {
"test": false,
"feef": 21,
"aeef": ["1","2","3"],
"test2": "a",
"test2": {"shush": "yay"},
"aaaa": null,
"aa": false
}';

//echo Test::fromJson(JSON)->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);
echo $json->toJson($var);


class Test3 {
use JSONModel;

/**
* @var array<Test2>
*/
#[ArrayType(Test2::class)]
public array $myArray;
}
$arr = $json->fromMappedArrayJson('[
{
"shush": "yipi"
},
{
"shush": "yipu"
}
]', Test2::class);

foreach ($arr as $val) {
echo $val->sheesh;
}

2 changes: 1 addition & 1 deletion uppm.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "interaapps/jsonplus",
"version": "1.0.2",
"version": "1.0.3",
"phpVersion": ">8.0",
"repositories": [],
"run": {
Expand Down

0 comments on commit 2b0e878

Please sign in to comment.