From f4c95885916fb2b82ab11995d02083a76077ac2d Mon Sep 17 00:00:00 2001 From: Mikel Larreategi Date: Thu, 30 Jul 2026 12:25:42 +0200 Subject: [PATCH 1/2] Add IJsonCompatible converter for IRichTextValue to handle nested RichText fields --- src/plone/restapi/serializer/configure.zcml | 1 + src/plone/restapi/serializer/converters.py | 10 ++++++++++ .../restapi/tests/test_serializer_converters.py | 14 ++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/plone/restapi/serializer/configure.zcml b/src/plone/restapi/serializer/configure.zcml index 881b0e16fd..4d81ac889c 100644 --- a/src/plone/restapi/serializer/configure.zcml +++ b/src/plone/restapi/serializer/configure.zcml @@ -89,6 +89,7 @@ + diff --git a/src/plone/restapi/serializer/converters.py b/src/plone/restapi/serializer/converters.py index 0cb024d071..bcb91b9468 100644 --- a/src/plone/restapi/serializer/converters.py +++ b/src/plone/restapi/serializer/converters.py @@ -175,6 +175,16 @@ def timedelta_converter(value): return json_compatible(value.total_seconds()) +@adapter(IRichTextValue) +@implementer(IJsonCompatible) +def richtext_converter(value): + return { + "data": json_compatible(value.raw), + "content-type": json_compatible(value.mimeType), + "encoding": json_compatible(value.encoding), + } + + @adapter(IRichTextValue, IDexterityContent) @implementer(IContextawareJsonCompatible) class RichtextDXContextConverter: diff --git a/src/plone/restapi/tests/test_serializer_converters.py b/src/plone/restapi/tests/test_serializer_converters.py index 6dd98b651e..ffbbf177c1 100644 --- a/src/plone/restapi/tests/test_serializer_converters.py +++ b/src/plone/restapi/tests/test_serializer_converters.py @@ -4,6 +4,7 @@ from DateTime import DateTime from persistent.list import PersistentList from persistent.mapping import PersistentMapping +from plone.app.textfield.value import RichTextValue from plone.restapi.serializer.converters import json_compatible from plone.restapi.testing import PLONE_RESTAPI_DX_INTEGRATION_TESTING from unittest import TestCase @@ -218,3 +219,16 @@ def test_i18n_message(self): def test_missing_value(self): self.assertEqual(None, json_compatible(Missing.Value)) + + def test_richtext_value_nested(self): + value = RichTextValue( + raw="

foo

", mimeType="text/html", outputMimeType="text/x-html-safe" + ) + self.assertEqual( + { + "data": "

foo

", + "content-type": "text/html", + "encoding": "utf-8", + }, + json_compatible({"foo": value})["foo"], + ) From 9b9055af0941ab529f283e663a00747d36ec99ef Mon Sep 17 00:00:00 2001 From: Mikel Larreategi Date: Thu, 30 Jul 2026 12:25:53 +0200 Subject: [PATCH 2/2] Add news item --- news/2039.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/2039.bugfix diff --git a/news/2039.bugfix b/news/2039.bugfix new file mode 100644 index 0000000000..3e1bcd08d9 --- /dev/null +++ b/news/2039.bugfix @@ -0,0 +1 @@ +Add IJsonCompatible converter for IRichTextValue to handle nested RichText fields safely.