Skip to content

Fix JSON schema provider crash for Dict/List fields (#2037) - #2038

Merged
davisagli merged 3 commits into
mainfrom
fix-dict-json-schema-crash
Aug 7, 2026
Merged

Fix JSON schema provider crash for Dict/List fields (#2037)#2038
davisagli merged 3 commits into
mainfrom
fix-dict-json-schema-crash

Conversation

@erral

@erral erral commented Jul 30, 2026

Copy link
Copy Markdown
Member

This PR fixes a crash in the JSON schema providers for Dict and List fields when they are defined without specifying sub-types (key_type or value_type).

In zope.schema, these sub-types default to None. The previous implementation was unconditionally attempting to adapt these None values to IJsonSchemaProvider, leading to a ComponentLookupError.

Changes:

  • Replaced getMultiAdapter with queryMultiAdapter and added safety checks for key_type and value_type in DictJsonSchemaProvider and CollectionJsonSchemaProvider.
  • Added regression tests in src/plone/restapi/tests/test_types.py.

Fixes #2037

@mister-roboto

Copy link
Copy Markdown

@erral thanks for creating this Pull Request and helping to improve Plone!

TL;DR: Finish pushing changes, pass all other checks, then paste a comment:

@jenkins-plone-org please run jobs

To ensure that these changes do not break other parts of Plone, the Plone test suite matrix needs to pass, but it takes 30-60 min. Other CI checks are usually much faster and the Plone Jenkins resources are limited, so when done pushing changes and all other checks pass either start all Jenkins PR jobs yourself, or simply add the comment above in this PR to start all the jobs automatically.

Happy hacking!

@erral

erral commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

@erral
erral force-pushed the fix-dict-json-schema-crash branch from 20f7e5b to d9ff170 Compare July 30, 2026 12:38
@erral

erral commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

I have refined the fix to follow a more localized approach as discussed.

Refined Changes:

  • Restored DefaultJsonSchemaProvider and the general properties loop in utils.py to their original strict states, maintaining standard registration and architectural patterns.
  • Implemented try...except NotImplementedError blocks specifically within DictJsonSchemaProvider and CollectionJsonSchemaProvider.
  • This ensures that if a nested field (like the generic schema.Field() in standard Plone Collections) lacks a specialized schema provider, it is gracefully handled (skipped or returned as an empty schema) without crashing the entire endpoint.
  • Maintained regression tests verifying the fix against missing sub-types and generic fields.

The implementation is now robust against the reported crash while preserving the strictness of the base classes.

@erral

erral commented Aug 4, 2026

Copy link
Copy Markdown
Member Author

@jenkins-plone-org please run jobs

Comment thread news/2037.bugfix Outdated
Comment thread src/plone/restapi/tests/test_types.py Outdated
Comment thread src/plone/restapi/tests/test_types.py Outdated
Comment thread src/plone/restapi/types/adapters.py Outdated
Comment thread src/plone/restapi/types/adapters.py
Comment thread src/plone/restapi/types/adapters.py Outdated
@erral

erral commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

Thank you for your review @davisagli, nevertheless, applying your suggestion, the Collection type information is not properly rendered and it crashes.

The reason for the defensive code in my PR is that standard Plone Collections use schema.Field() within their query attribute to handle values of varying types.

Currently, DefaultJsonSchemaProvider is registered for IField but raises NotImplementedError. If I use a strict getMultiAdapter as suggested, the /@types/Collection endpoint crashes out-of-the-box for every Plone site.

I agree we shouldn't hide errors for specific field types, but schema.Field looks like a legitimate 'untyped' field.

If you still think that the defensive strategy doesn't feel right, I could implement a more specific adapter for IField objects, omitting the JSON type.

This way, we can have the adapter approach for this kind of fields while raising NotImplementedErrors for other unknown kinds of fields.

@davisagli

Copy link
Copy Markdown
Member

@erral I see. I think we should update DefaultJsonSchemaProvider to return None from get_type instead of raising NotImplementedError, and update get_schema to only add the type key if get_type() returns a value that is not None. This seems to be the correct way to represent an unspecified type in JSON Schema.

Please also add a test for the case you're talking about (Dict with value_type=schema.Field())

@erral
erral force-pushed the fix-dict-json-schema-crash branch from d2e6305 to 40e3941 Compare August 6, 2026 19:21
@erral

erral commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

Thanks, that makes sense!

@davisagli

Copy link
Copy Markdown
Member

@jenkins-plone-org please run jobs

@davisagli
davisagli merged commit fe7e1b4 into main Aug 7, 2026
16 of 20 checks passed
@davisagli
davisagli deleted the fix-dict-json-schema-crash branch August 7, 2026 01:49
@gyst

gyst commented Aug 7, 2026

Copy link
Copy Markdown
Member

I have no clue what you're doing here, but I happened to run tests on a buildout with local checkouts and that threw me a nasty error:

zope.configuration.config.ConfigurationConflictError: Conflicting configuration actions
  For: ('adapter', (<InterfaceClass plone.app.textfield.interfaces.IRichTextValue>,), <InterfaceClass plone.restapi.interfaces.IJsonCompatible>, '')
    File "/app/dev/plone.restapi/src/plone/restapi/serializer/configure.zcml", line 92.2-92.59
        <adapter factory=".converters.richtextvalue_converter" />
    File "/app/tmp/eggs/v5/cp312/plone.app.blocks-8.0.0-py3.12-linux-x86_64.egg/plone/app/blocks/configure.zcml", line 27.2-30.8
        <adapter
            factory=".utils.richtext_json_compatible"
            zcml:condition="installed plone.app.textfield"
            />

I don't know if that's an error in my specific setup or a more generic error condition not caught yet.

@erral

erral commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

plone.app.blocks has its own RichTextValue adapter, like the one we have added to plone.restapi: see https://github.com/plone/plone.app.blocks/blob/master/src/plone/app/blocks/configure.zcml#L27-L30

We didn't catch this because as plone.app.blocks is not part of plone core neither our own tests nor Jenkins caught this.

I am opening an issue in plone.app.blocks referencing this PR.

@erral

erral commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

The relevant issue is #1584 not this one.

@davisagli

Copy link
Copy Markdown
Member

@gyst Thanks for pointing that out. I'll follow up on @erral's PR in plone.app.blocks

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Collection type information is not properly serialized

4 participants