Skip to content

Commit 2b0e878

Browse files
committed
Added #[ArrayType(type)] and changed README
1 parent 36a81fa commit 2b0e878

File tree

8 files changed

+211
-46
lines changed

8 files changed

+211
-46
lines changed

README.md

Lines changed: 79 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,99 @@
22

33
## Getting started
44

5+
### JSONPlus instance
56
```php
67
<?php
8+
use de\interaapps\jsonplus\JSONPlus;
9+
use de\interaapps\jsonplus\serializationadapter\impl\JsonSerializationAdapter;
10+
use de\interaapps\jsonplus\serializationadapter\impl\phpjson\PHPJsonSerializationAdapter;
711

12+
$jsonPlus = JSONPlus::createDefault();
13+
$obj = $jsonPlus->fromJson('{"obj": "hello world"}');
14+
echo $obj->string; // -> hello world
15+
16+
// Enabling pretty printing
17+
$jsonPlus->setPrettyPrinting(true);
18+
19+
echo $jsonPlus->toJson($obj); // -> {"obj": "hello world"}
20+
21+
/// Other drivers
22+
// Default if json_decode exists in JSONPlus::createDefault()
23+
$jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter());
24+
// Custom JSON implementation
25+
$jsonPlus = new JSONPlus(new JsonSerializationAdapter());
26+
```
27+
28+
### Model
29+
```php
30+
<?php
31+
use de\interaapps\jsonplus\JSONPlus;
32+
use de\interaapps\jsonplus\JSONModel;
833
use de\interaapps\jsonplus\attributes\Serialize;
9-
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;
34+
use de\interaapps\jsonplus\attributes\ArrayType;
1035

11-
class Test2 {
12-
use JSONModel;
13-
14-
#[Serialize("my_array")]
15-
public array $myArray;
36+
class Organisation {
37+
public string $name;
1638
}
1739

18-
class Test {
19-
// Adds the Test#toJson and Test::fromJson functions
40+
class User {
2041
use JSONModel;
2142

22-
public string $test;
23-
public Test2 $test2;
43+
public int id;
44+
45+
#[Serialize("firstName")]
46+
public string firstName;
47+
48+
#[Serialize(hidden: true)]
49+
public string password;
50+
51+
public ?Organisation $organisation;
52+
53+
// Set Type for array:
54+
#[ArrayType(User::class)]
55+
public array $friends;
2456
}
2557

26-
$test = Test::fromJson('{
27-
"test": "Hello World",
28-
"test2": {
29-
"my_array": ["Hello There"]
30-
}
31-
}');
58+
$json = '{
59+
"id": 12343,
60+
"first_name": "Jeff",
61+
"organisation": {
62+
"name": "InteraApps"
63+
},
64+
"friends": [
65+
{
66+
"id": 3245,
67+
"first_name": "John",
68+
"friends": []
69+
}
70+
]
71+
}';
72+
73+
// Decoding the JSON
74+
$user = User::fromJson($json);
75+
76+
echo "Hello. My name is ".$user->first_name.", I have the ID ".$user->id
77+
."and I'm in the organisation ".$user->organisation->name."\n";
78+
79+
foreach ($user->friends as $friend) {
80+
echo "One of my friends: ".$friend->name."\n";
81+
}
3282

33-
echo $test->toJson();
83+
// Encoding to JSON
84+
echo $user->toJson();
3485

35-
// Custom JSONPlus Instance
86+
// Decode typed JSON-array
3687
$jsonPlus = JSONPlus::createDefault();
37-
// $jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter());
38-
$arrJson = $jsonPlus->toJson([
39-
"A", "B", "C"
40-
]);
41-
echo $arrJson;
42-
// '["A", "B", "C"]'
43-
44-
echo $jsonPlus->fromJson($arrJson)[0];
45-
// "A"
46-
47-
// Setting JSONModal
48-
Test::setJsonPlusInstance($jsonPlus);
49-
// For all (Default instance)
50-
JSONPlus::$default = $jsonPlus;
51-
52-
/// Using other JSON-Drivers
53-
// Uses PHPs default json_encode and json_decode methods
54-
$jsonPlus = new JSONPlus(new PHPJsonSerializationAdapter());
55-
// Uses an custom implementation of JSON. This will be automatically chosen by JSONPlus::createDefault when json_decode doesn't exist
56-
$jsonPlus = new JSONPlus(new JsonSerializationAdapter());
88+
$users = $jsonPlus->fromMappedArrayJson('[...]', User::class);
89+
foreach ($users as $user) {}
90+
```
91+
`Tip`: If you are using PHPStorm or any other intelligent IDE you might add PHP-Docs to some fields.
92+
93+
For Typed Arrays:
94+
```php
95+
/**
96+
* @var array<User>
97+
*/
5798
```
5899

59100
## Installation

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "interaapps/jsonplus",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"type": "library",
55
"authors": [
66
{

src/main/de/interaapps/jsonplus/JSONPlus.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use de\interaapps\jsonplus\serializationadapter\impl\JsonSerializationAdapter;
55
use de\interaapps\jsonplus\serializationadapter\impl\phpjson\PHPJsonSerializationAdapter;
66
use de\interaapps\jsonplus\serializationadapter\SerializationAdapter;
7+
use de\interaapps\jsonplus\typemapper\ArrayTypeMapper;
78
use de\interaapps\jsonplus\typemapper\ObjectTypeMapper;
89
use de\interaapps\jsonplus\typemapper\PassThroughTypeMapper;
910
use de\interaapps\jsonplus\typemapper\StdClassObjectTypeMapper;
@@ -29,7 +30,7 @@ public function __construct(
2930
"int" => $this->passThroughTypeMapper,
3031
"double" => $this->passThroughTypeMapper,
3132
"bool" => $this->passThroughTypeMapper,
32-
"array" => $this->passThroughTypeMapper,
33+
"array" => new ArrayTypeMapper($this),
3334
"boolean" => $this->passThroughTypeMapper,
3435
"NULL" => $this->passThroughTypeMapper,
3536
"stdClass" => new StdClassObjectTypeMapper($this),
@@ -46,6 +47,28 @@ public function fromJson(string $json, string|null $type = null){
4647
return $this->map($this->serializationAdapter->fromJson($json), $type);
4748
}
4849

50+
/**
51+
* @template T
52+
* @param string $json The input json
53+
* @param class-string<T> $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically)
54+
* @return array<T>
55+
* */
56+
public function fromMappedArrayJson(string $json, string $type) : array {
57+
return $this->mapTypedArray($this->serializationAdapter->fromJson($json), $type);
58+
}
59+
/**
60+
* @template T
61+
* @param array $arr
62+
* @param class-string<T> $type A class (className::class), type (example: "array", "int"...) or null (Detects type automatically)
63+
* @return array<T>
64+
* */
65+
public function mapTypedArray(array $arr, string $type) : array {
66+
$out = [];
67+
foreach ($arr as $i=>$v)
68+
$out[$i] = $this->map($v, $type);
69+
return $out;
70+
}
71+
4972
/**
5073
* @template T
5174
* @param $o
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace de\interaapps\jsonplus\attributes;
4+
5+
use Attribute;
6+
7+
#[Attribute]
8+
class ArrayType {
9+
/**
10+
* @param class-string $value
11+
*/
12+
public function __construct(
13+
public string $value
14+
){
15+
}
16+
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
namespace de\interaapps\jsonplus\typemapper;
3+
4+
5+
use de\interaapps\jsonplus\JSONPlus;
6+
7+
class ArrayTypeMapper implements TypeMapper {
8+
public function __construct(
9+
private JSONPlus $jsonPlus
10+
){
11+
}
12+
13+
public function map(mixed $o, string $type, $entriesType = null): mixed {
14+
if ($entriesType !== null) {
15+
return $this->jsonPlus->mapTypedArray($o, $entriesType);
16+
} else
17+
return $o;
18+
}
19+
20+
public function mapToJson(mixed $o, string $type): mixed {
21+
$out = [];
22+
foreach ($o as $i=>$val) {
23+
$out[$i] = $this->jsonPlus->mapToJson($val);
24+
}
25+
return $out;
26+
}
27+
}

src/main/de/interaapps/jsonplus/typemapper/ObjectTypeMapper.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace de\interaapps\jsonplus\typemapper;
33

44

5+
use de\interaapps\jsonplus\attributes\ArrayType;
56
use de\interaapps\jsonplus\attributes\Serialize;
67
use de\interaapps\jsonplus\JSONPlus;
78
use ReflectionClass;
@@ -30,8 +31,18 @@ public function map(mixed $o, string $type): mixed {
3031
continue 2;
3132
}
3233

33-
if ($o != null && isset($o->{$name}))
34+
if ($o != null && isset($o->{$name})) {
35+
// Mapping Array if #[ArrayType] is given
36+
if (is_array($o->{$name})) {
37+
$arrayTypeAttribs = $property->getAttributes(ArrayType::class);
38+
foreach ($arrayTypeAttribs as $attrib) {
39+
$property->setValue($oo, $this->jsonPlus->mapTypedArray($o->{$name}, $attrib->newInstance()->value));
40+
continue 2;
41+
}
42+
}
43+
3444
$property->setValue($oo, $this->jsonPlus->map($o?->{$name}, strval($property->getType())));
45+
}
3546
}
3647
}
3748

@@ -46,6 +57,7 @@ public function mapToJson(mixed $o, string $type): mixed {
4657
foreach ($class->getProperties() as $property) {
4758
if (!$property->isStatic()) {
4859
$name = $property?->getName();
60+
4961
$overrideName = $property?->getName();
5062
$serializeAttribs = $property->getAttributes(Serialize::class);
5163
foreach ($serializeAttribs as $attrib) {
@@ -55,8 +67,27 @@ public function mapToJson(mixed $o, string $type): mixed {
5567
continue 2;
5668
}
5769

58-
if ($o != null && isset($o->{$name}))
70+
71+
if ($o !== null && isset($o->{$name})) {
72+
// Mapping Array if #[ArrayType] is given
73+
if (is_array($o->{$name})) {
74+
$outArr = [];
75+
foreach ($o->{$name} as $i=>$entry)
76+
$outArr[$i] = $this->jsonPlus->mapToJson($entry);
77+
$oo[$overrideName] = $outArr;
78+
continue;
79+
}
80+
81+
// Mapping Type
82+
if (gettype($o?->{$name}) == "object") {
83+
$class = get_class($o?->{$name});
84+
if ($class != "stdClass") {
85+
$oo[$overrideName] = $this->mapToJson($o?->{$name}, $class);
86+
continue;
87+
}
88+
}
5989
$oo[$overrideName] = $o?->{$name};
90+
}
6091
}
6192
}
6293
return (object) $oo;

src/test/testbootstrap.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
// Init
33

4+
use de\interaapps\jsonplus\attributes\ArrayType;
45
use de\interaapps\jsonplus\attributes\Serialize;
56
use de\interaapps\jsonplus\JSONModel;
67
use de\interaapps\jsonplus\JSONPlus;
@@ -17,6 +18,7 @@
1718
echo "Testing:\n";
1819

1920
class Test2 {
21+
#[Serialize("shush")]
2022
public string $sheesh;
2123
}
2224

@@ -47,14 +49,38 @@ public function setName(string $name): Test {
4749
"test": false,
4850
"feef": 21,
4951
"aeef": ["1","2","3"],
50-
"test2": "a",
52+
"test2": {"shush": "yay"},
5153
"aaaa": null,
5254
"aa": false
5355
}';
5456

55-
//echo Test::fromJson(JSON)->toJson();
57+
echo Test::fromJson(JSON)->toJson();
5658
$json = new JSONPlus(new JsonSerializationAdapter());
5759
$var = $json->fromJson(JSON, Test::class);
5860

5961
echo $var->name."\n";
60-
echo $json->toJson($var);
62+
echo $json->toJson($var);
63+
64+
65+
class Test3 {
66+
use JSONModel;
67+
68+
/**
69+
* @var array<Test2>
70+
*/
71+
#[ArrayType(Test2::class)]
72+
public array $myArray;
73+
}
74+
$arr = $json->fromMappedArrayJson('[
75+
{
76+
"shush": "yipi"
77+
},
78+
{
79+
"shush": "yipu"
80+
}
81+
]', Test2::class);
82+
83+
foreach ($arr as $val) {
84+
echo $val->sheesh;
85+
}
86+

uppm.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "interaapps/jsonplus",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"phpVersion": ">8.0",
55
"repositories": [],
66
"run": {

0 commit comments

Comments
 (0)