Skip to content

Commit

Permalink
Merge pull request #23 from localheinz/feature/unescape
Browse files Browse the repository at this point in the history
Enhancement: Remove unescaping capabilities
  • Loading branch information
localheinz authored Jan 5, 2018
2 parents 1d3bbb0 + 5fffc79 commit c5aba96
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 271 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,60 @@ Run
$ composer require localheinz/json-printer
```

## Usage

Let's assume we have a variable `$json` which contains some JSON that is not indented:

```json
{"name":"Andreas Möller","emoji":"🤓","urls":["https://localheinz.com","https://github.com/localheinz","https://twitter.com/localheinz"]}
```

or indented with 4 spaces:

```json
{
"name":"Andreas Möller",
"emoji":"🤓",
"urls":[
"https://localheinz.com",
"https://github.com/localheinz",
"https://twitter.com/localheinz"
]
}
```

but we want to indent it with 2 spaces (or tabs).

This is where `Localheinz\Json\Printer\Printer` comes in

```php
use Localheinz\Json\Printer\Printer;

$printer = new Printer();

$printed = $printer->print(
$json,
' '
);
```

which results in `$printed`:

```json
{
"name":"Andreas Möller",
"emoji":"🤓",
"urls":[
"https://localheinz.com",
"https://github.com/localheinz",
"https://twitter.com/localheinz"
]
}
```

:bulb: Note that this printer is only concerned with normalizing the
indentation, no escaping or un-escaping occurs.

## Contributing

Please have a look at [`CONTRIBUTING.md`](.github/CONTRIBUTING.md).
Expand Down
59 changes: 17 additions & 42 deletions src/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,29 @@ final class Printer implements PrinterInterface
* @see https://github.com/composer/composer/blob/1.6.0/src/Composer/Json/JsonFormatter.php#L25-L126
* @see https://www.daveperrett.com/articles/2008/03/11/format-json-with-php/
*
* @param string $original
* The primary objective of the adoption is
*
* - turn static method into an instance method
* - allow to specify indent
*
* If you observe closely, the options for un-escaping unicode characters and slashes have been removed. Since this
* package requires PHP 7, there is no need to implement this in user-land code.
* @see http://php.net/manual/en/function.json-encode.php
* @see http://php.net/manual/en/json.constants.php
*
* @param string $json
* @param string $indent
* @param bool $unEscapeUnicode
* @param bool $unEscapeSlashes
*
* @throws \InvalidArgumentException
*
* @return string
*/
public function print(
string $original,
string $indent = ' ',
bool $unEscapeUnicode = false,
bool $unEscapeSlashes = false
): string {
if (null === \json_decode($original) && JSON_ERROR_NONE !== \json_last_error()) {
public function print(string $json, string $indent = ' '): string
{
if (null === \json_decode($json) && JSON_ERROR_NONE !== \json_last_error()) {
throw new \InvalidArgumentException(\sprintf(
'"%s" is not valid JSON.',
$original
$json
));
}

Expand All @@ -54,7 +58,7 @@ public function print(

$printed = '';
$indentLevel = 0;
$length = \strlen($original);
$length = \strlen($json);
$withinStringLiteral = false;
$stringLiteral = '';
$noEscape = true;
Expand All @@ -63,7 +67,7 @@ public function print(
/**
* Grab the next character in the string.
*/
$character = \substr($original, $i, 1);
$character = \substr($json, $i, 1);

/**
* Are we inside a quoted string literal?
Expand All @@ -86,35 +90,6 @@ public function print(
* Process string literal if we are about to leave it.
*/
if ('' !== $stringLiteral) {
/**
* Un-escape slashes in string literal.
*/
if ($unEscapeSlashes) {
$stringLiteral = \str_replace('\\/', '/', $stringLiteral);
}

/**
* Un-escape unicode in string literal.
*/
if ($unEscapeUnicode && \function_exists('mb_convert_encoding')) {
/**
* @see https://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
*/
$stringLiteral = \preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function (array $match) {
$length = \strlen($match[1]);

if ($length % 2) {
return \str_repeat('\\', $length - 1) . \mb_convert_encoding(
\pack('H*', $match[2]),
'UTF-8',
'UCS-2BE'
);
}

return $match[0];
}, $stringLiteral);
}

$printed .= $stringLiteral . $character;
$stringLiteral = '';

Expand Down
7 changes: 1 addition & 6 deletions src/PrinterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,5 @@

interface PrinterInterface
{
public function print(
string $original,
string $indent = ' ',
bool $unEscapeUnicode = false,
bool $unEscapeSlashes = false
): string;
public function print(string $json, string $indent = ' '): string;
}
52 changes: 2 additions & 50 deletions test/Bench/PrinterBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,58 +40,10 @@ public function benchJsonEncode()
*/
public function benchPrint()
{
$this->print(
false,
false
);
}

/**
* @Revs(5)
*/
public function benchPrintWithUnEscapeUnicode()
{
$this->print(
true,
false
);
}

/**
* @Revs(5)
*/
public function benchPrintWithUnEscapeSlashes()
{
$this->print(
false,
true
);
}

/**
* @Revs(5)
*/
public function benchPrintWithUnEscapeUnicodeAndUnEscapeSlashes()
{
$this->print(
true,
true
);
}

private function print(bool $unEscapeUnicode, bool $unEscapeSlashes)
{
$original = \file_get_contents($this->filename);

$indent = ' ';
$json = \file_get_contents($this->filename);

$printer = new Printer();

$printer->print(
$original,
$indent,
$unEscapeUnicode,
$unEscapeSlashes
);
$printer->print($json);
}
}
Loading

0 comments on commit c5aba96

Please sign in to comment.