aboutsummaryrefslogtreecommitdiffstats
path: root/includes/json/JsonUnserializer.php
diff options
context:
space:
mode:
authorPetr Pchelko <ppchelko@wikimedia.org>2020-11-17 17:26:53 -0700
committerPetr Pchelko <ppchelko@wikimedia.org>2020-11-19 08:32:21 -0700
commitdbdc2a3cd339991abaf918c3390614bb0221ece4 (patch)
treea594ae727b75b4348cf5dab6322c9bb4be7bf7de /includes/json/JsonUnserializer.php
parent6e5c7e97b4e9ffc320371fba684954f72c6dce04 (diff)
downloadmediawikicore-dbdc2a3cd339991abaf918c3390614bb0221ece4.tar.gz
mediawikicore-dbdc2a3cd339991abaf918c3390614bb0221ece4.zip
Introduce JsonCodec to help with serialization/deserialization
Change-Id: I5433090ae8e2b3f2a4590cc404baf838025546ce
Diffstat (limited to 'includes/json/JsonUnserializer.php')
-rw-r--r--includes/json/JsonUnserializer.php87
1 files changed, 15 insertions, 72 deletions
diff --git a/includes/json/JsonUnserializer.php b/includes/json/JsonUnserializer.php
index 555179c06409..4bde309d356a 100644
--- a/includes/json/JsonUnserializer.php
+++ b/includes/json/JsonUnserializer.php
@@ -21,93 +21,36 @@
namespace MediaWiki\Json;
-use FormatJson;
use InvalidArgumentException;
/**
- * Helper class to unserialize instances of JsonUnserializable.
+ * Deserializes things from JSON.
*
+ * @since 1.36
* @package MediaWiki\Json
*/
-class JsonUnserializer {
+interface JsonUnserializer {
/**
- * Name of the property where the class information is stored.
- * @internal
- */
- public const TYPE_ANNOTATION = '_type_';
-
- /**
- * Restore an instance of JsonUnserializable subclass from the JSON serialization.
+ * Restore an instance of simple type or JsonUnserializable subclass
+ * from the JSON serialization. It supports passing array/object to
+ * allow manual decoding of the JSON string if needed.
+ *
+ * @note JSON objects are unconditionally unserialized as PHP associative
+ * arrays and not as instances of \stdClass.
*
* @param array|string|object $json
- * @param string|null $expectedClass What class to expect in unserialization. If null, no expectation.
+ * @param string|null $expectedClass What class to expect in unserialization.
+ * If null, no expectation. Must be a descendant of JsonUnserializable.
* @throws InvalidArgumentException if the passed $json can't be unserialized.
- * @return JsonUnserializable
+ * @return mixed
*/
- public function unserialize( $json, string $expectedClass = null ) : JsonUnserializable {
- if ( is_string( $json ) ) {
- $json = FormatJson::decode( $json, true );
- if ( !$json ) {
- // TODO: in PHP 7.3, we can use JsonException
- throw new InvalidArgumentException( 'Bad JSON' );
- }
- }
-
- if ( is_object( $json ) ) {
- $json = (array)$json;
- }
-
- if ( !is_array( $json ) ) {
- throw new InvalidArgumentException(
- 'Expected array, got ' . gettype( $json )
- );
- }
-
- if ( !$this->canMakeNewFromValue( $json ) ) {
- throw new InvalidArgumentException( 'JSON did not have ' . self::TYPE_ANNOTATION );
- }
-
- $class = $json[self::TYPE_ANNOTATION];
- if ( !class_exists( $class ) || !is_subclass_of( $class, JsonUnserializable::class ) ) {
- throw new InvalidArgumentException( "Target class {$class} does not exist" );
- }
-
- $obj = $class::newFromJsonArray( $this, $json );
-
- // Check we haven't accidentally unserialized a godzilla if we were told we are not expecting it.
- if ( $expectedClass && !is_a( $obj, $expectedClass ) ) {
- $actualClass = get_class( $obj );
- throw new InvalidArgumentException( "Expected {$expectedClass}, got {$actualClass}" );
- }
- return $obj;
- }
+ public function unserialize( $json, string $expectedClass = null );
/**
- * Helper to unserialize an array of JsonUnserializable instances or scalars.
+ * Helper to unserialize an array of JsonUnserializable instances or simple types.
* @param array $array
* @return array
*/
- public function unserializeArray( array $array ) : array {
- $unserializedExtensionData = [];
- foreach ( $array as $key => $value ) {
- if ( $this->canMakeNewFromValue( $value ) ) {
- $unserializedExtensionData[$key] = $this->unserialize( $value );
- } else {
- $unserializedExtensionData[$key] = $value;
- }
- }
- return $unserializedExtensionData;
- }
-
- /**
- * Is it likely possible to make a new instance from $json serialization?
- * @param mixed $json
- * @return bool
- */
- private function canMakeNewFromValue( $json ) : bool {
- $classAnnotation = self::TYPE_ANNOTATION;
- return ( is_array( $json ) && array_key_exists( $classAnnotation, $json ) ) ||
- ( is_object( $json ) && isset( $json->$classAnnotation ) );
- }
+ public function unserializeArray( array $array ) : array;
}