Skip to content

[5.4] Fix: custom field named "images" overrides core article images in API response#47306

Open
icybersanjay wants to merge 3 commits intojoomla:5.4-devfrom
icybersanjay:fix-47301-api-images-custom-field
Open

[5.4] Fix: custom field named "images" overrides core article images in API response#47306
icybersanjay wants to merge 3 commits intojoomla:5.4-devfrom
icybersanjay:fix-47301-api-images-custom-field

Conversation

@icybersanjay
Copy link

Summary

Fixes #47301

When a com_content custom field has the name images, it silently overwrites the core article images property during prepareItem(). This causes the JSON:API response (GET /api/index.php/v1/content/articles/{id}) to return an empty array for images instead of the article's actual intro/fulltext image data.

The same collision could occur for any other core field name (e.g. urls, metadata) if a custom field uses the same name.

What was changed

api/components/com_content/src/View/Articles/JsonapiView.php

  1. prepareItem(): Skip custom field hydration when the property already exists on the item object, so core article data is never overwritten by a custom field with a colliding name.
  2. displayItem() / displayList(): Guard against appending a custom field name to fieldsToRenderItem / fieldsToRenderList when that name is already present (prevents duplicate attribute keys in the JSON:API output).

tests/System/integration/api/com_content/Articles.cy.js

Added a Cypress system test that:

  • Creates a custom field with name = "images" scoped to com_content.article
  • Creates an article with intro/fulltext images set
  • Asserts that GET /content/articles/{id} returns the core article images.image_intro value (not an empty array)
  • Cleans up both #__content and #__fields rows after each test

Testing instructions

  1. Install a clean Joomla site.
  2. Enable the API Authentication - Token plugin and copy the token from a Super Admin user.
  3. Create a custom field for Articles with the name images (any type, e.g. Media).
  4. Create an article and set both an intro image and a full-text image.
  5. Call: GET /api/index.php/v1/content/articles/{id} with the bearer token.
  6. Before this fix: attributes.images is [] and the custom field value is also absent.
  7. After this fix: attributes.images contains the correct image_intro / image_fulltext URLs; the custom field is not duplicated.

Environment tested

  • PHP 8.3
  • MySQL 9.x
  • Joomla 5.4-dev (bug also present in 6.0.x)

Notes

The fix is intentionally minimal: core properties defined on the item object at the time prepareItem() is called take precedence over any custom field with a matching name. Custom fields with unique names continue to work exactly as before.

… response

When a com_content custom field has the name "images", it was silently
overwriting the core article images property during prepareItem(), causing
the JSON:API response to return an empty array for images instead of the
article's actual intro/fulltext image data.

Fix by skipping custom field hydration for any property that already exists
on the item object. Also prevent duplicate field names being appended to
fieldsToRenderItem/fieldsToRenderList when a custom field name collides with
a core field already declared in those arrays.

Fixes joomla#47301
@richard67
Copy link
Member

There is another, a little bit older PR for the same issue: #47304 .

@brianteeman
Copy link
Contributor

This cannot be the correct solution as the next question would be why isnt the content of my custom field being included in the api response. All you are doing here is silently removing a valid field to solve one part of the problem.

@laoneo
Copy link
Member

laoneo commented Mar 5, 2026

What else should be done to fix the issue @brianteeman ? Renaming the custom field in the response?

@brianteeman
Copy link
Contributor

Perhaps with a custom field prefix. Simply throwing away the field content silently is just pushing the valid bug to someone else to fix in the future

Joomla CS rules enforce unqualified native function calls inside
a namespace — use `property_exists()` not `\property_exists()`.
@alikon
Copy link
Contributor

alikon commented Mar 6, 2026

custom field not rendered

image
{
    "links": {
        "self": "http:\/\/localhost:7060\/api\/index.php\/v1\/content\/articles"
    },
    "data": [
        {
            "type": "articles",
            "id": "1",
            "attributes": {
                "id": 1,
                "asset_id": 101,
                "title": "test_imagesin_fileds",
                "alias": "test-imagesin-fileds",
                "state": 1,
                "access": 1,
                "created": "2026-03-05 10:44:12",
                "created_by": 657,
                "created_by_alias": "",
                "modified": "2026-03-05 11:03:06",
                "featured": 0,
                "language": "*",
                "hits": 0,
                "publish_up": "2026-03-05 10:44:12",
                "publish_down": null,
                "note": "",
                "images": {
                    "image_intro": "http:\/\/localhost:7060\/images\/sampledata\/fruitshop\/apple.jpg#joomlaImage:\/\/local-images\/sampledata\/fruitshop\/apple.jpg?width=375&height=281",
                    "image_intro_alt": "",
                    "float_intro": "",
                    "image_intro_caption": "",
                    "image_fulltext": "http:\/\/localhost:7060\/images\/sampledata\/fruitshop\/bananas_2.jpg#joomlaImage:\/\/local-images\/sampledata\/fruitshop\/bananas_2.jpg?width=300&height=352",
                    "image_fulltext_alt": "",
                    "float_fulltext": "",
                    "image_fulltext_caption": ""
                },
                "metakey": "",
                "metadesc": "",
                "metadata": {
                    "robots": "",
                    "author": "",
                    "rights": ""
                },
                "version": 3,
                "featured_up": null,
                "featured_down": null,
                "typeAlias": "com_content.article",
                "text": " ",
                "tags": []
            },
            "relationships": {
                "category": {
                    "data": {
                        "type": "categories",
                        "id": "2"
                    }
                },
                "created_by": {
                    "data": {
                        "type": "users",
                        "id": "657"
                    }
                },
                "tags": {
                    "data": []
                }
            }
        }
    ],
    "meta": {
        "total-pages": 1
    }
}

@alikon
Copy link
Contributor

alikon commented Mar 6, 2026

I have tested this item 🔴 unsuccessfully on 2e34e59


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/47306.

…ng it

When a custom field shares a name with a core article property (e.g. "images"),
the previous guard silently dropped the custom field value entirely.

Instead, assign the custom field to a "cf_{name}" key on the item so that:
- The core article property (images, urls, etc.) is preserved as-is.
- The custom field value still appears in the API response as cf_images.

Apply the same prefix logic in displayItem() and displayList() so the
cf_{name} key is included in fieldsToRenderItem / fieldsToRenderList and
therefore serialised into the JSON:API attributes.
@icybersanjay
Copy link
Author

okay @brianteeman, now I've added prefix 'cf_' in case of field names collision

@PixedBo
Copy link

PixedBo commented Mar 6, 2026

Does adding a prefix such as “cf_” to custom fields create a problem with all apps that already use APIs and call custom fields by their name without a prefix?
Does such a change mean having to change the JSON management system that comes back from Joomla?

@alikon
Copy link
Contributor

alikon commented Mar 6, 2026

imho it's a wont fix, just choose a non conflicting name for custom fields

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web Services API: images not returned in the JSON of single article GET when a custom field named "images" is present

7 participants