Yurik has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/258196

Change subject: Allow JSON values to be included in the API results
......................................................................

Allow JSON values to be included in the API results

JSON value is added with
  $this->getResult()->addValue( null, 'graph', $data, ApiResult::JSON_VALUE );

JSON formatter will add the value as a subtree:
{
    "graph": {
        "_1": 1,
        "_type": 2,
        "version": 2
    }
}

XML formatter will output content:
<api>
  <graph xml:space="preserve">{"_1":1,"_type":2,"version":2}</graph>
</api>

Bug: T120380
Change-Id: I7bd8646da281f4cbc320b1e77f5285abc3254ae4
---
M includes/api/ApiFormatJson.php
M includes/api/ApiResult.php
2 files changed, 34 insertions(+), 8 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/96/258196/1

diff --git a/includes/api/ApiFormatJson.php b/includes/api/ApiFormatJson.php
index a319be3..8b7a72e 100644
--- a/includes/api/ApiFormatJson.php
+++ b/includes/api/ApiFormatJson.php
@@ -78,7 +78,7 @@
                                        $opt |= $params['utf8'] ? 
FormatJson::ALL_OK : FormatJson::XMLMETA_OK;
                                        $transform = array(
                                                'BC' => array(),
-                                               'Types' => array( 
'AssocAsObject' => true ),
+                                               'Types' => array( 
'AssocAsObject' => true, 'JsonAsObject' => true ),
                                                'Strip' => 'all',
                                        );
                                        break;
@@ -87,7 +87,7 @@
                                case 'latest':
                                        $opt |= $params['ascii'] ? 
FormatJson::XMLMETA_OK : FormatJson::ALL_OK;
                                        $transform = array(
-                                               'Types' => array( 
'AssocAsObject' => true ),
+                                               'Types' => array( 
'AssocAsObject' => true, 'JsonAsObject' => true ),
                                                'Strip' => 'all',
                                        );
                                        break;
diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php
index e28cb82..3a6bdbb 100644
--- a/includes/api/ApiResult.php
+++ b/includes/api/ApiResult.php
@@ -64,6 +64,12 @@
        const NO_VALIDATE = 12;
 
        /**
+        * For addValue(), setValue() and similar functions, treat data as a 
single JSON value.
+        * @since 1.26
+        */
+       const JSON_VALUE = 16;
+
+       /**
         * Key for the 'indexed tag name' metadata item. Value is string.
         * @since 1.25
         */
@@ -288,7 +294,7 @@
         */
        public static function setValue( array &$arr, $name, $value, $flags = 0 
) {
                if ( ( $flags & ApiResult::NO_VALIDATE ) !== 
ApiResult::NO_VALIDATE ) {
-                       $value = self::validateValue( $value );
+                       $value = self::validateValue( $value, $flags );
                }
 
                if ( $name === null ) {
@@ -327,10 +333,23 @@
        /**
         * Validate a value for addition to the result
         * @param mixed $value
+        * @param int $flags Zero or more OR-ed flags. For now only handles 
JSON_VALUE
         * @return array|mixed|string
         */
-       private static function validateValue( $value ) {
+       private static function validateValue( $value, $flags = 0 ) {
                global $wgContLang;
+
+               if ( $flags & ApiResult::JSON_VALUE ) {
+                       // Wrap json value and cache it for XML formatter and 
size check
+                       $json = FormatJson::encode( $value, false, 
FormatJson::ALL_OK );
+                       if ( $json === false ) {
+                               throw new InvalidArgumentException( "Cannot 
encode value as JSON for ApiResult" );
+                       }
+                       // Cache string for XML formatter and size check and 
skip all further value validation
+                       $result = array( self::META_TYPE => 'json', '_value' => 
$value );
+                       self::setContentValue( $result, '*', $json );
+                       return $result;
+               }
 
                if ( is_object( $value ) ) {
                        // Note we use is_callable() here instead of instanceof 
because
@@ -404,7 +423,7 @@
                if ( $this->checkingSize && !( $flags & 
ApiResult::NO_SIZE_CHECK ) ) {
                        // self::valueSize needs the validated value. Then flag
                        // to not re-validate later.
-                       $value = self::validateValue( $value );
+                       $value = self::validateValue( $value, $flags );
                        $flags |= ApiResult::NO_VALIDATE;
 
                        $newsize = $this->size + self::valueSize( $value );
@@ -939,6 +958,9 @@
 
                        // Apply transformation
                        switch ( $type ) {
+                               case 'json':
+                                       return empty( 
$transformTypes['JsonAsObject'] ) ? (object)$data : $metadata['_value'];
+
                                case 'assoc':
                                        $metadata[self::META_TYPE] = 'assoc';
                                        $data += $keepMetadata;
@@ -1089,9 +1111,13 @@
        private static function valueSize( $value ) {
                $s = 0;
                if ( is_array( $value ) ) {
-                       foreach ( $value as $k => $v ) {
-                               if ( !self::isMetadataKey( $s ) ) {
-                                       $s += self::valueSize( $v );
+                       if ( $value[self::META_TYPE] === 'json' ) {
+                               $s = strlen( $value['*'] );
+                       } else {
+                               foreach ( $value as $k => $v ) {
+                                       if ( !self::isMetadataKey( $s ) ) {
+                                               $s += self::valueSize( $v );
+                                       }
                                }
                        }
                } elseif ( is_scalar( $value ) ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/258196
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7bd8646da281f4cbc320b1e77f5285abc3254ae4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Yurik <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to