WordPress.org

Make WordPress Core

Opened 10 months ago

Last modified 10 months ago

#50012 new defect (bug)

REST API: Fields filter does not work with "object" collection responses

Reported by: TimothyBlynJacobs Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 4.8
Component: REST API Keywords:
Focuses: Cc:

Description

As reported in #core-restapi, trying to use the _fields parameter with the wp/v2/taxonomies route does not return the expected result. Instead, an empty set is returned.

http://trunk.test/wp-json/wp/v2/taxonomies?_fields=name

Looking into it, this happens with both the taxonomies and types route because they return an "object" collection response. That is, instead of returning an array, they return an object keyed by the taxonomy or post type slug.

{
  "category": {
    "name": "Categories",
    "slug": "category"
  }
}

instead of...

[
  {
    "name": "Categories",
    "slug": "category"
  }
]

This means that the wp_is_numeric_array check in rest_filter_response_fields to try and determine whether this is a collection response fails and it treats the response as a single object, and then ends up removing all the properties.

It appears that the _fields check inside of the controller itself work, it is just the "fallback" filtering that doesn't work and ends up corrupting the response.

A possible fix would be to somehow mark that a response has already been filtered, and rest_filter_response_fields does not need to be run. This would probably also be a performance benefit.

Change History (2)

This ticket was mentioned in Slack in #core-restapi by timothybjacobs. View the logs.


10 months ago

This ticket was mentioned in PR #250 on WordPress/wordpress-develop by johnwatkins0.


10 months ago

Trac ticket: https://core.trac.wordpress.org/ticket/50012

This fixes support for the _fields parameter in REST requests for taxonomies and post types. These REST responses take the form of objects rather than arrays -- e.g. { category: { ...data }, post_tag: { ...data } } -- and the _fields filter was being applied to that final data set, filtering out the top-level items.

The _fields parameter is also applied earlier in the get_items logic to the nested objects themselves. This fix removes _fields from the request after that occurs and before the final response is processed.

### Alternatives

One alternative option is here: https://github.com/johnwatkins0/wordpress-develop/commit/b81852609627f32bd841754d005ccbea68495053 This adds a couple of new methods to the WP_REST_Request class. Another possibility I looked at was adding a filter at the beginning rest_filter_response_fields and adding a filter callback in the endpoint classes that have the nested object structure. But both those options do essentially the same thing as this PR with much more code.

The drawback to this approach is it doesn't automatically apply to new endpoints that have similar structures, but the other approaches I thought of don't either. It might be worth exploring an option in register_rest_route or somewhere similar to indicate that get_items for a given endpoint returns an object rather than an array and _fields filtering should not be applied to the final object, but I also think anyone building custom endpoints at this level can figure out their own workarounds.

Note: See TracTickets for help on using tickets.