diff options
author | Petr Pchelko <ppchelko@wikimedia.org> | 2020-11-17 17:26:53 -0700 |
---|---|---|
committer | Petr Pchelko <ppchelko@wikimedia.org> | 2020-11-19 08:32:21 -0700 |
commit | dbdc2a3cd339991abaf918c3390614bb0221ece4 (patch) | |
tree | a594ae727b75b4348cf5dab6322c9bb4be7bf7de /includes/json/JsonUnserializer.php | |
parent | 6e5c7e97b4e9ffc320371fba684954f72c6dce04 (diff) | |
download | mediawikicore-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.php | 87 |
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; } |