Skip to content

Remove plone.jsonserializer dependency - #114

Merged
petschki merged 8 commits into
masterfrom
replace-jsonserializer
Mar 26, 2026
Merged

Remove plone.jsonserializer dependency#114
petschki merged 8 commits into
masterfrom
replace-jsonserializer

Conversation

@petschki

@petschki petschki commented Mar 19, 2026

Copy link
Copy Markdown
Member
  • I signed and returned the Plone Contributor Agreement, and received and accepted an invitation to join a team in the Plone GitHub organization.
  • I verified there aren't any other open pull requests for the same change.
  • I followed the guidelines in Contributing to Plone.
  • I successfully ran code quality checks on my changes locally.
  • I successfully ran tests on my changes locally.
  • If needed, I added new tests for my changes.
  • If needed, I added documentation for my changes.
  • I included a change log entry in my commits.

Since plone.jsonserializer is very old and not actively maintained we should remove the dependency here.

json_compatible is already there in plone.restapi

schema_compatible is unfortunately not that easy to replace with plone.restapis schema deserializer, so I simply took over the factory from plone.jsonserializer for now.

fixes #92

@petschki
petschki force-pushed the replace-jsonserializer branch from 0be6dac to 452f43b Compare March 19, 2026 07:35
@petschki
petschki marked this pull request as ready for review March 26, 2026 08:33
@petschki
petschki requested review from mauritsvanrees and thet March 26, 2026 08:35

@mauritsvanrees mauritsvanrees left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems okay.

But I am missing the big picture. What is wrong with plone.jsonserializer? If it is too big, then why do we replace it with the even bigger plone.restapi?

from plone.app.textfield import RichText
from plone.app.textfield import RichTextValue
except ImportError:
self.skipTest("plone.app.textfield not available")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of self.skipTest I would prefer marking the test with something like @unittest.skipUnless(RichText, "plone.app.testfield not available"). And then try/except that import at the top, falling back to RichText = None. Or similar with @unittest.skipIf.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, will do that in the next PR...

@petschki

Copy link
Copy Markdown
Member Author

The idea is to get rid of a package which is

  • old and unmaintained
  • only used in ecosystem and only by plone.app.blocks

@mauritsvanrees mauritsvanrees left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable.

With plone.jsonserializer it was possible to register new adapters though. I don't know if anyone ever did that. Maybe someone did, to fix serializing RelationValues.

So I wonder if we can offer a simple hook for this. We can create a register_converter function. I tried it here by extracting the first converter into a separate function:

_converters = []
_marker = object()

def register_converter(method):
    _converters.append(method)


def dict_converter(value, schema_or_field, default):
    # dict + schema interface: convert each field value
    if not isinstance(value, dict) or IField.providedBy(schema_or_field):
        return default
    if not value:
        return {}
    result = {}
    for key, val in value.items():
        if key not in schema_or_field:
            continue
        result[str(key)] = schema_compatible(val, schema_or_field[key])
    return result

register_converter(dict_converter)

def schema_compatible(value, schema_or_field):
    """Convert a value to zope.schema compatible data.

    Replacement for plone.jsonserializer's schema_compatible function.
    """
    if value is None:
        return value

    for converter in _converters:
        result = converter(value, schema_or_field, default=_marker)
        if result is not _marker:
            return result
    # I extracted the next one into a separate function:
    # # dict + schema interface: convert each field value
    # if isinstance(value, dict) and not IField.providedBy(schema_or_field):
    #     if not value:
    #         return {}
    #     result = {}
    #     for key, val in value.items():
    #         if key not in schema_or_field:
    #             continue
    #         result[str(key)] = schema_compatible(val, schema_or_field[key])
    #     return result

I think our current converters can stay inline, and always be called first. We could iterate over the registered converters at the end, right before falling back to simply return value.

What do you think?

But this could be done as an improvement later, so let me approve your current PR.

@petschki

Copy link
Copy Markdown
Member Author

Good idea. Lets do this after merging this.

Maybe we can also implement more restapi logic here (lookup registered deserializers instead of converting it on. our own)

@petschki
petschki merged commit d18ed8b into master Mar 26, 2026
9 checks passed
@petschki
petschki deleted the replace-jsonserializer branch March 26, 2026 13:20
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.

Replace plone.jsonserializer with plone.restapi (de)serializers

2 participants