Skip to content

Commit

Permalink
Merge pull request #2 from ergebnis/feature/json-schema-validator
Browse files Browse the repository at this point in the history
Enhancement: Import `Json` from `ergebnis/json-schema-validator`
  • Loading branch information
localheinz committed Dec 10, 2022
2 parents a632ef8 + 95a853f commit d5106ad
Show file tree
Hide file tree
Showing 25 changed files with 457 additions and 92 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -11,9 +11,11 @@ For a full diff see [`c020e6f...main`][c020e6f...main].
### Added

- Imported `Json` from [`ergebnis/json-normalizer`](https://github.com/ergebnis/json-normalizer/tree/3.0.0) ([#1]), by [@localheinz]
- Imported and merged `Json` from [`ergebnis/json-schema-validator`](https://github.com/ergebnis/json-schema-validator/tree/3.2.0) ([#2]), by [@localheinz]

[c020e6f...main]: https://github.com/ergebnis/json/compare/c020e6f...main

[#1]: https://github.com/ergebnis/json/pull/1
[#2]: https://github.com/ergebnis/json/pull/2

[@localheinz]: https://github.com/localheinz
54 changes: 52 additions & 2 deletions README.md
Expand Up @@ -39,7 +39,7 @@ $encoded = <<<TXT
"foo
TXT;
$json = Json\Json::fromEncoded($encoded); // throws Json\Exception\InvalidJsonEncoded
$json = Json\Json::fromString($encoded); // throws Json\Exception\NotJson
```
Create a `Json` object from a valid JSON `string`:
Expand All @@ -57,7 +57,57 @@ $encoded = <<<JSON
}
JSON;
$json = Json\Json::fromEncoded($encoded); // instance of Json\Json
$json = Json\Json::fromString($encoded); // instance of Json\Json
```
### Create a `Json` object from a file
Create a `Json` object from a file that does not exist:
```php
<?php
declare(strict_types=1);
use Ergebnis\Json;
$json = Json\Json::fromFile(__DIR__ . '/does-not-exist.json'); // throws Json\Exception\FileDoesNotExist
```
Create a `Json` object from a file that can not be read:
```php
<?php
declare(strict_types=1);
use Ergebnis\Json;
$json = Json\Json::fromFile(__DIR__ . '/can-not-be-read.json'); // throws Json\Exception\FileCanNotBeRead
```
Create a `Json` object from a file that does not contain a valid JSON `string`:
```php
<?php
declare(strict_types=1);
use Ergebnis\Json;
$json = Json\Json::fromFile(__DIR__ . '/README.MD'); // throws Json\Exception\FileDoesNotContainJson
```
Create a `Json` object from a file that contains a valid JSON `string`:
```php
<?php
declare(strict_types=1);
use Ergebnis\Json;
$json = Json\Json::fromFile(__DIR__ . '/contains-json.json'); // instance of Json\Json
```
## Changelog
Expand Down
15 changes: 9 additions & 6 deletions psalm-baseline.xml
@@ -1,16 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.1.0@4defa177c89397c5e14737a80fe4896584130674">
<file src="src/Json.php">
<MixedArgument occurrences="1">
<MixedArgument occurrences="2">
<code>$decoded</code>
<code>$decoded</code>
</MixedArgument>
<MixedAssignment occurrences="1">
<MixedAssignment occurrences="2">
<code>$decoded</code>
<code>$decoded</code>
</MixedAssignment>
</file>
<file src="test/Unit/JsonTest.php">
<InvalidArgument occurrences="1">
<code>testFromEncodedReturnsJson</code>
</InvalidArgument>
<file src="test/DataProvider/JsonProvider.php">
<MoreSpecificReturnType occurrences="2">
<code>\Generator&lt;string, array{0: string}&gt;</code>
<code>\Generator&lt;string, array{0: string}&gt;</code>
</MoreSpecificReturnType>
</file>
</files>
25 changes: 25 additions & 0 deletions src/Exception/FileCanNotBeRead.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2022 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json
*/

namespace Ergebnis\Json\Exception;

final class FileCanNotBeRead extends \InvalidArgumentException
{
public static function file(string $name): self
{
return new self(\sprintf(
'File "%s" can not be read.',
$name,
));
}
}
25 changes: 25 additions & 0 deletions src/Exception/FileDoesNotContainJson.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2022 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json
*/

namespace Ergebnis\Json\Exception;

final class FileDoesNotContainJson extends \InvalidArgumentException
{
public static function file(string $name): self
{
return new self(\sprintf(
'File "%s" does not contain a valid JSON string.',
$name,
));
}
}
25 changes: 25 additions & 0 deletions src/Exception/FileDoesNotExist.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2022 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json
*/

namespace Ergebnis\Json\Exception;

final class FileDoesNotExist extends \InvalidArgumentException
{
public static function file(string $name): self
{
return new self(\sprintf(
'File "%s" does not exist.',
$name,
));
}
}
36 changes: 0 additions & 36 deletions src/Exception/InvalidJsonEncoded.php

This file was deleted.

25 changes: 25 additions & 0 deletions src/Exception/NotJson.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2022 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json
*/

namespace Ergebnis\Json\Exception;

final class NotJson extends \InvalidArgumentException implements Exception
{
public static function value(string $value): self
{
return new self(\sprintf(
'Value "%s" is not a valid JSON string.',
$value,
));
}
}
40 changes: 37 additions & 3 deletions src/Json.php
Expand Up @@ -28,9 +28,9 @@ private function __construct(
}

/**
* @throws Exception\InvalidJsonEncoded
* @throws Exception\NotJson
*/
public static function fromEncoded(string $encoded): self
public static function fromString(string $encoded): self
{
try {
$decoded = \json_decode(
Expand All @@ -40,7 +40,41 @@ public static function fromEncoded(string $encoded): self
\JSON_THROW_ON_ERROR,
);
} catch (\JsonException) {
throw Exception\InvalidJsonEncoded::fromEncoded($encoded);
throw Exception\NotJson::value($encoded);
}

return new self(
$encoded,
$decoded,
);
}

/**
* @throws Exception\FileCanNotBeRead
* @throws Exception\FileDoesNotContainJson
* @throws Exception\FileDoesNotExist
*/
public static function fromFile(string $file): self
{
if (!\is_file($file)) {
throw Exception\FileDoesNotExist::file($file);
}

$encoded = \file_get_contents($file);

if (!\is_string($encoded)) {
throw Exception\FileCanNotBeRead::file($file);
}

try {
$decoded = \json_decode(
$encoded,
true,
512,
\JSON_THROW_ON_ERROR,
);
} catch (\JsonException) {
throw Exception\FileDoesNotContainJson::file($file);
}

return new self(
Expand Down
63 changes: 63 additions & 0 deletions test/DataProvider/JsonProvider.php
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2022 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/json
*/

namespace Ergebnis\Json\Test\DataProvider;

use Ergebnis\DataProvider;

final class JsonProvider extends DataProvider\AbstractProvider
{
/**
* @return \Generator<string, array{0: string}>
*/
public static function validString(): \Generator
{
yield from self::provideDataForValues(\array_map(static function (string $file): string {
$value = \file_get_contents($file);

if (!\is_string($value)) {
throw new \RuntimeException(\sprintf(
'File "%s" does not exist or can not be read.',
$file,
));
}

return \trim($value);
}, self::filesContainingValidJson()));
}

/**
* @return \Generator<string, array{0: string}>
*/
public function validFile(): \Generator
{
yield from self::provideDataForValues(self::filesContainingValidJson());
}

/**
* @return array<string, string>
*/
private static function filesContainingValidJson(): array
{
return [
'array' => __DIR__ . '/../Fixture/Json/valid/array.json',
'bool-false' => __DIR__ . '/../Fixture/Json/valid/bool-false.json',
'bool-true' => __DIR__ . '/../Fixture/Json/valid/bool-true.json',
'float' => __DIR__ . '/../Fixture/Json/valid/float.json',
'int' => __DIR__ . '/../Fixture/Json/valid/int.json',
'object' => __DIR__ . '/../Fixture/Json/valid/object.json',
'string-arbitrary' => __DIR__ . '/../Fixture/Json/valid/string-arbitrary.json',
'string-empty' => __DIR__ . '/../Fixture/Json/valid/string-empty.json',
];
}
}
2 changes: 2 additions & 0 deletions test/Fixture/Json/not-valid/object.json
@@ -0,0 +1,2 @@
{
"foo":
4 changes: 4 additions & 0 deletions test/Fixture/Json/valid/array.json
@@ -0,0 +1,4 @@
[
"foo",
"bar"
]
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/bool-false.json
@@ -0,0 +1 @@
false
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/bool-true.json
@@ -0,0 +1 @@
true
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/float.json
@@ -0,0 +1 @@
3.14
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/int.json
@@ -0,0 +1 @@
9001
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/null.json
@@ -0,0 +1 @@
null
4 changes: 4 additions & 0 deletions test/Fixture/Json/valid/object.json
@@ -0,0 +1,4 @@
{
"foo": "bar",
"bar": "baz"
}
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/string-arbitrary.json
@@ -0,0 +1 @@
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
1 change: 1 addition & 0 deletions test/Fixture/Json/valid/string-empty.json
@@ -0,0 +1 @@
""

0 comments on commit d5106ad

Please sign in to comment.