API:JSON version 2

suffers from a number of shortcomings that make it more difficult to use than necessary. Many of these are inherited from the underlying data structure being designed for the XML format.

To address this, after discussion MediaWiki 1.25 introduces a new JSON response format. It is not the default, you only get results in the new format if you specify, and it's only for the   and   formats (and their human-readable   and   variants).

Maintaining backwards compatibility

 *  XXX from mediawiki-api-announce mailing

Without specifying formatversion=2, things should be backwards-compatible. But there are some caveats:


 * Modules that were previously outputting raw booleans in JSON may now have those properties being output using the standard convention: empty-string for true and absent for false. Instances of this should be reported in Phabricator  to be fixed, please tag with #MediaWiki-API  and the tag for the relevant extension.
 * format=xml will now reversibly mangle tag and attribute names that are not valid XML, instead of just outputting invalid XML.
 * Previously-announced breaking changes to log entry parameter formatting, that are not actually part of this general result formatting change but were made at about the same time.

API module implementers: ensuring backwards compatibility

 *  XXX

The general theme is that the ApiResult arrays now have more metadata, which the API core code uses to apply a backwards-compatible transformation for clients that don't request, and optional transformation so JSON output needn't be limited by restrictions of XML. At the same time, ApiResult and ApiFormatXml are improved be easier for developers to use.

To ensure backwards compatibility – clients that don't request  get the same results as in previous releases – developers may need to update code.


 * Several ApiResult methods have been deprecated. If your extension is maintained in Gerrit, these should have already been taken care of for you (with the exception of T95168  where work is ongoing), but new code will need to avoid the deprecated methods.
 * All ApiResult methods that operate on a passed-in array (rather than internal data) are now static, and static versions of all relevant data- and metadata-manipulation methods are provided. This should reduce the need for passing ApiResult instances around just to be able to set metadata.
 * Properties with names beginning with underscores are reserved for API metadata (following the lead of existing "_element" and "_subelements"), and will be stripped from output. Such properties may be marked as non-metadata using ApiResult::setPreserveKeysList, if necessary.
 * PHP-arrays can now be tagged with "array types" to indicate whether they should be output as arrays or hashes. This is particularly useful to fix T12887 .
 * The "*" property is deprecated in favor of a properly-named property and special metadata to identify it for XML format and for back-transformation. Use ApiResult::setContentValue instead of ApiResult::setContent and all the details are handled for you.
 * ApiFormatXml will no longer throw an exception if you forget to call ApiResult::setIndexedTagName!
 * ApiFormatXml will now reversibly mangle tag and attribute names that are not valid XML, instead of irreversibly mangling spaces and outputting invalid XML for other stuff.
 * ApiResult will now validate data added (e.g. adding resources or non-finite floats will throw an exception) and auto-convert objects. The ApiSerializable interface can be used to control object conversion, if __toString or cast-to-array is inappropriate.
 * Actual booleans should now be added to ApiResult, and will be automatically converted to the old convention (empty-string for true and absent for false) when needed for backwards compatibility. Code that was violating the old convention will need to use the new ApiResult::META_BC_BOOLS metadata property to prevent this conversion.
 * Modules outputting as {"key":{"*":"value"}} to avoid large strings in XML attributes can now output as {"key":"value"} while still maintaining value  in XML format, using ApiResult::META_BC_SUBELEMENTS. New code should use ApiResult::setSubelementsList instead.
 * Modules outputting hashes as [{"name":"key1","*":"value1"},{"name":"key2","*":"value2"}] (due to the keys being invalid for XML) can now output as {"key1":"value1","key2":"value2"} in JSON while maintaining value1  value2  in XML format, using array types "kvp" or "BCkvp".

API modules that return JSON structures containing boolean values may also break clients without changes, E.g. EventLogging returning JSON Schema,

Changes to XML format
does not have a new results format. There are some changes to XML results:


 * From API/Architecture_work/Planning

Changes here will mostly be on the back-end; the actual data output to clients is intended to remain the same wherever possible. However, clients should be prepared for the following:
 * Result structure may no longer match the JSON format.
 * Tag and attribute names may be encoded when not conforming to XML requirements.
 * Result structure may change depending on the specific query. For example, passing both rvprop=content and rvdiffto=prev to prop=revisions will currently omit the diff from the result (bug 55371) (it should be throwing an error, but that's another bug). In the future, it's likely that this will return the content as the value of the node when rvdiffto is not supplied and as the value of a subnode of the node when it is.

For example, bug 43221 was fixed by changing the names of attributes such as "4::foo" to fit XML's restrictions. In the future, this would be fixed by either encoding the name (e.g. "_4.3A..3A.foo") or by changing the structure of output in only the XML format (e.g.  ).

On the MediaWiki code side, developers will see the following changes:
 * The XML formatter will no longer die if ApiResult::setIndexedTagName is forgotten. Instead, it will act as if that were called with something generic (e.g. ApiResult::setIndexedTagName( $array, 'item' )).
 * The XML formatter will no longer (be supposed to) raise an error when a node has both node content (ApiResult::setContent) and non-scalar attributes. Instead, it will simply shove the intended node content into a subnode.
 * Anything that's hard-coding '*' instead of using ApiResult::setContent is going to break.
 * There may be additional ApiResult calls required in some cases.

The future of "version 1" JSON response format
In some future release the old format=json will be deprecated, and eventually removed.

Using the new JSON results format
You can use  in your requests in MediaWiki 1.25, but do note that the output formatting isn't entirely stable yet and might change in MediaWiki 1.26.

Changes to JSON output format

 *  XXX from mediawiki-api-announce mailing

With, we can make some useful changes:
 * Return booleans as boolean true instead of empty-string. Where appropriate,[1] return boolean false instead of omitting the property.
 * Return empty objects in JSON as {}, rather than [].
 * Have action=query's "pages" be an array, instead of an object with page ids as keys that can be difficult to iterate.
 * Provide useful property names instead of '*'.
 * Eliminate useless indirection, e.g. {"text":"..."} instead of {"text":{"*":"..."}} and {"key1":"value1","key2":"value2"} instead of [{"name":"key1","*":"value1"},{"name":"key2","*":"value2"}].

If you see missed opportunities to make the above changes in existing formatversion=2 output, or if there are other changes that would make API output easier to use in JSON, please let MediaWiki API developers know! Phabricator  would be ideal (tag with #MediaWiki-API , and the appropriate extension's tag if applicable), or reply on the mediawiki-api mailing list .

[1]: Where the property is usually false, it's sometimes just bloat to include it.


 * XXX from API/Architecture_work/Planning, did all these happen

If you specify :
 * The existing 'utf8' option will be the default.
 * A new 'ascii' request parameter will be introduced for clients who need all non-ASCII codepoints escaped.
 * Anything using '*' as a key will be renamed to something more natural. In some cases this may result in something like "query.page[1].foo['*']" becoming simply "query.page[1].foo", and in others something like "query.page[1].foo.content".
 * Boolean result properties will use boolean true as the value, rather than the empty string. Whether a property will be present with a boolean false value or will continue to be entirely absent from the result when false will be determined on a case-by-case basis.
 * Result parameters that are already being returned as booleans may accidentally change to the empty-string style in the format=json output.
 * Page lists will be returned as arrays rather than objects with page_ids as keys. This will make it easier for clients to iterate over the results.
 * The 'indexpageids' parameter will be removed.
 * The JSON formatter currently has a tendency to return values that are normally objects as arrays when empty (bug 10887). This will be easily fixable.

On the MediaWiki code side, developers will see the following changes:
 * If anything is currently returning boolean values as actual booleans rather than the API standard empty-string, code will need to be changed to preserve this behavior in the non-sane output. The exact code change is yet to be decided, but will be something along the lines of having to pass such boolean values through some method on ApiResult.
 * There will be a way to explicitly tag a PHP array in the result as "array" or "object", much like how ApiResult::setIndexedTagName is used for the XML format.
 * Ambiguous cases, such as empty arrays or some kinds of arrays with integer keys, might throw an error if not explicitly tagged. If this would bother you, comment!