8000 [Serializer] Add options to JsonDecode and JsonEncode to wrap/unwrap json data by Simperfit · Pull Request #30894 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Serializer] Add options to JsonDecode and JsonEncode to wrap/unwrap json data #30894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
moved context option to public const and use the PropertyAccess to ac…
…cess any node
  • Loading branch information
nonanerz authored and Amrouche Hamza committed Apr 6, 2019
commit ea3bb6cf4f98edb212ee1a1af0a3fc792c233b9e
19 changes: 17 additions & 2 deletions src/Symfony/Component/Serializer/Encoder/JsonDecode.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Serializer\Exception\NotEncodableValueException;

/**
Expand Down Expand Up @@ -38,7 +39,9 @@ class JsonDecode implements DecoderInterface
self::ASSOCIATIVE => false,
self::OPTIONS => 0,
self::RECURSION_DEPTH => 512,
JsonEncoder::JSON_PROPERTY_PATH => null,
];
private $propertyAccessor;

/**
* Constructs a new JsonDecode instance.
Expand All @@ -57,14 +60,15 @@ public function __construct($defaultContext = [], int $depth = 512)
}

$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It adds a hard dependency on property access which is still a suggested dependency in the composer

}

/**
* Decodes data.
*
* @param string $data The encoded JSON string to decode
* @param string $format Must be set to JsonEncoder::FORMAT
* @param array $context An optional set of options for the JSON decoder; see below
* @param array $context an optional set of options for the JSON decoder; see below
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be reverted

*
* The $context array is a simple key=>value array, with the following supported keys:
*
Expand All @@ -80,6 +84,9 @@ public function __construct($defaultContext = [], int $depth = 512)
* json_decode_options: integer
* Specifies additional options as per documentation for json_decode
*
* JSON_PROPERTY_PATH: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lower case: that's the value of the constant, not its name

* Specifies property path and allow to unwrap data
*
* @return mixed
*
* @throws NotEncodableValueException
Expand All @@ -91,13 +98,21 @@ public function decode($data, $format, array $context = [])
$associative = $context[self::ASSOCIATIVE] ?? $this->defaultContext[self::ASSOCIATIVE];
$recursionDepth = $context[self::RECURSION_DEPTH] ?? $this->defaultContext[self::RECURSION_DEPTH];
$options = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];

$propertyPath = $context[JsonEncoder::JSON_PROPERTY_PATH] ?? $this->defaultContext[JsonEncoder::JSON_PROPERTY_PATH];
$decodedData = json_decode($data, $associative, $recursionDepth, $options);

if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotEncodableValueException(json_last_error_msg());
}

if ($propertyPath) {
if ($this->propertyAccessor->isReadable($decodedData, $propertyPath)) {
$decodedData = $this->propertyAccessor->getValue($decodedData, $propertyPath);
} else {
$decodedData = null;
}
}

return $decodedData;
}

Expand Down
27 changes: 26 additions & 1 deletion src/Symfony/Component/Serializer/Encoder/JsonEncode.php
< 8000 td class="blob-code blob-code-addition js-file-line"> * Wrap data before encoding.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\Serializer\Encoder;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Serializer\Exception\NotEncodableValueException;

/**
Expand All @@ -24,13 +25,16 @@ class JsonEncode implements EncoderInterface

private $defaultContext = [
self::OPTIONS => 0,
JsonEncoder::JSON_PROPERTY_PATH => null,
];
private $propertyAccessor;

/**
* @param array $defaultContext
*/
public function __construct($defaultContext = [])
{
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
if (!\is_array($defaultContext)) {
@trigger_error(sprintf('Passing an integer as first parameter of the "%s()" method is deprecated since Symfony 4.2, use the "json_encode_options" key of the context instead.', __METHOD__), E_USER_DEPRECATED);

Expand All @@ -48,8 +52,12 @@ public function __construct($defaultContext = [])
public function encode($data, $format, array $context = [])
{
$jsonEncodeOptions = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];
$encodedJson = json_encode($data, $jsonEncodeOptions);
$propertyPath = $context[JsonEncoder::JSON_PROPERTY_PATH] ?? $this->defaultContext[JsonEncoder::JSON_PROPERTY_PATH];

if ($propertyPath) {
$data = $this->wrapEncodableData($propertyPath, $data);
}
$encodedJson = json_encode($data, $jsonEncodeOptions);
if (JSON_ERROR_NONE !== json_last_error() && (false === $encodedJson || !($jsonEncodeOptions & JSON_PARTIAL_OUTPUT_ON_ERROR))) {
throw new NotEncodableValueException(json_last_error_msg());
}
Expand All @@ -64,4 +72,21 @@ public function supportsEncoding($format)
{
return JsonEncoder::FORMAT === $format;
}

/**
*
* @param string $propertyPath
* @param mixed $data
*
* @return array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the docblock should be removed in favor of real types

*/
private function wrapEncodableData($propertyPath, $data)
{
$wrappedData = array();

$this->propertyAccessor->setValue($wrappedData, $propertyPath, $data);

return $wrappedData;
}
}
3 changes: 2 additions & 1 deletion src/Symfony/Component/Serializer/Encoder/JsonEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
*/
class JsonEncoder implements EncoderInterface, DecoderInterface
{
const FORMAT = 'json';
public const FORMAT = 'json';
public const JSON_PROPERTY_PATH = 'json_property_path';

protected $encodingImpl;
protected $decodingImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ public function decodeProvider()

$assoc = ['foo' => 'bar'];

return [
['{"foo": "bar"}', $stdClass, []],
['{"foo": "bar"}', $assoc, ['json_decode_associative' => true]],
];
return array(
array('{"foo": "bar"}', $stdClass, array()),
array('{"foo": "bar"}', $assoc, array('json_decode_associative' => true)),
array('{"baz": {"foo": "bar"}}', $stdClass, array(JsonEncoder::JSON_PROPERTY_PATH => 'baz')),
array('{"baz": {"foo": "bar"}}', null, array(JsonEncoder::JSON_PROPERTY_PATH => 'baz.inner')),
array('{"baz": {"foo": "bar"}}', $assoc, array(JsonEncoder::JSON_PROPERTY_PATH => '[baz]', 'json_decode_associative' => true)),
array('{"baz": {"foo": "bar"}}', $assoc, array(JsonEncoder::JSON_PROPERTY_PATH => '[baz]', 'json_decode_associative' => true)),
array('{"baz": {"foo": "bar", "inner": {"key": "value"}}}', array('key' => 'value'), array(JsonEncoder::JSON_PROPERTY_PATH => '[baz][inner]', 'json_decode_associative' => true)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see fabbot

);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function encodeProvider()
return [
[[], '[]', []],
[[], '{}', ['json_encode_options' => JSON_FORCE_OBJECT]],
[['bar' => 'foo'], '{"baz":{"bar":"foo"}}', [JsonEncoder::JSON_PROPERTY_PATH => '[baz]']],
];
}

Expand Down
0