{"id":2007,"date":"2025-09-10T14:14:43","date_gmt":"2025-09-10T12:14:43","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/?p=2007"},"modified":"2025-12-05T12:46:24","modified_gmt":"2025-12-05T11:46:24","slug":"characterescapes-jacksons-hidden-gem","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/characterescapes-jackson-s-hidden-gem\/","title":{"rendered":"CharacterEscapes: Jackson&#8217;s hidden gem"},"content":{"rendered":"<p>At <a href=\"https:\/\/www.kestra.io\">Kestra<\/a>, the data orchestration platform I work for, we had an issue ([#10326] (<a href=\"https:\/\/github.com\/kestra-io\/kestra\/issues\/10326\">https:\/\/github.com\/kestra-io\/kestra\/issues\/10326<\/a>)) opened by a user reporting a problem with the PostgreSQL database and the Unicode character <code>\\u0000<\/code>. A workflow task that returned this character in its output was failing.<\/p>\n<p>After investigation, PostgreSQL refuses to store a JSONB entry containing this character because it has no textual representation. This is because it is the null character in Unicode, which is not allowed in JSON, which represents null with the character string <code>null<\/code>.<\/p>\n<p>A hidden feature of Jackson, which we use for our JSON serialization layer, comes into play: <code>CharacterEscapes<\/code>.\nThis class allows us to configure how Jackson will escape special characters and allows us to escape the Unicode character <code>\\u0000<\/code> to avoid crashing a workflow task that would return it in the output.<\/p>\n<pre><code class=\"language-java\">public class SafeguardCharacterEscapes extends CharacterEscapes { \/\/ &lt;1&gt;\n    private static final SerializableString NULL = new SerializedString(&quot;null&quot;); \/\/ &lt;2&gt;\n\n    private final int[] asciiEscapes;\n\n    SafeguardCharacterEscapes() {\n        \/\/ &lt;3&gt; Start with the standard JSON escapes\n        asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();\n        \/\/ &lt;4&gt; And then specify that the null character should be escaped\n        asciiEscapes[0] = CharacterEscapes.ESCAPE_CUSTOM;\n    }\n\n    @Override\n    public int[] getEscapeCodesForAscii() {\n        return asciiEscapes;\n    }\n\n    @Override\n    public SerializableString getEscapeSequence(int ch) {\n        if (ch == 0) {\n            return NULL; \/\/ &lt;5&gt;\n        }\n        return null; \/\/ &lt;6&gt;\n    }\n}\n<\/code><\/pre>\n<ol><li>We create our own implementation of <code>CharacterEscapes<\/code>, which will be used when configuring the Jackson <code>ObjectMapper<\/code>. See below.<\/li>\n<li>We define a pre-calculated String that will be used when serializing the character; it will return the String <code>null<\/code>.<\/li>\n<li>We pre-calculate the escape codes for the ASCII character range. Since these characters are the most commonly used, they have a fast path via a correspondence table that we pre-calculate here by retrieving the standard escape codes.<\/li>\n<li>We replace the standard escape code for the ASCII character <code><\/code>, which corresponds to the Unicode character <code>\\u0000<\/code>, because the first 128 Unicode characters coincide with the ASCII range, with a custom escape sequence. Custom sequences are defined dynamically by the <code>getEscapeSequence(int)<\/code> method.<\/li>\n<li>We return our pre-calculated String as a custom sequence for the character corresponding to the <em>code point<\/em> 0.<\/li>\n<li>We return <code>null<\/code> for all others, indicating that there is no other custom escape sequence.<\/li>\n<\/ol>\n<p>Last step, we&#8217;ll configure Jackson&#8217;s <code>ObjectMapper<\/code> to use our custom <code>CharacterEscapes<\/code>:<\/p>\n<pre><code class=\"language-java\">ObjectMapper objectMapper = new ObjectMapper();\nobjectMapper.getFactory().setCharacterEscapes(new SafeguardCharacterEscapes());\n<\/code><\/pre>\n<p>And that&#8217;s it, no more failing tasks! Thank you Jackson and your hidden gem <code>CharacterEscapes<\/code>!<\/p>\n<p>Finally, after discussion, we decided not to integrate this change into Kestra. If the character is not supported by PostgreSQL, there is a good reason. A task output must be representable in JSON, and <code>\\0000<\/code> is not valid JSON.\nBut even though we didn&#8217;t integrate this change, I found the feature interesting enough to share it with you ;).<\/p>","protected":false},"excerpt":{"rendered":"<p>At Kestra, the data orchestration platform I work for, we had an issue ([#10326] (<a href=\"https:\/\/github.com\/kestra-io\/kestra\/issues\/10326\">https:\/\/github.com\/kestra-io\/kestra\/issues\/10326<\/a>)) opened by a user reporting a problem with the PostgreSQL database and the Unicode character \\u0000. A workflow task that returned this character in its output was failing. After investigation, PostgreSQL refuses to store a JSONB entry containing this character because it has no textual representation. This is because it is the null character in Unicode, which is not allowed in JSON, which represents null&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/characterescapes-jackson-s-hidden-gem\/\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"federated","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[230,211],"class_list":["post-2007","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-jackson","tag-kestra"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1847,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/jooq-tip-ne-convertissez-pas-jsonb-en-string\/","url_meta":{"origin":2007,"position":0},"title":"jOOQ tip: don&#8217;t convert JSONB to a String","author":"admin","date":"Wednesday October 23rd, 2024","format":false,"excerpt":"A few weeks ago, while investigating possible performance improvements for Kestra's JDBC backend, I noticed that a method we were using to map an entity to be persisted in the database into its JSONB representation was taking up a lot of time in our CPU profiles. In the following flame\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/366507373-c44206a5-0085-43cc-902e-97756319b0ea-1024x737.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/366507373-c44206a5-0085-43cc-902e-97756319b0ea-1024x737.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/366507373-c44206a5-0085-43cc-902e-97756319b0ea-1024x737.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1786,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/concevoir-un-saas-multitenant\/","url_meta":{"origin":2007,"position":1},"title":"Designing a multi-tenant SaaS","author":"admin","date":"Tuesday March  5th, 2024","format":false,"excerpt":"This article is based on my talk Designing a multi-tenant SaaS given at Cloud Nord on October 12, 2023. Kestra is a highly scalable data scheduling and orchestration platform that creates, executes, schedules and monitors millions of complex pipelines. For an introduction to Kestra, you can read my article on\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-software-architecture-1024x576.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-software-architecture-1024x576.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-software-architecture-1024x576.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1611,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-kestra\/","url_meta":{"origin":2007,"position":2},"title":"Introduction to Kestra","author":"admin","date":"Monday March  6th, 2023","format":false,"excerpt":"Kestra is an open-source data orchestrator and scheduler. With Kestra, data workflows, called flows, use the YAML format and are executed by its engine via an API call, the user interface, or a trigger (webhook, schedule, SQL query, Pub\/Sub message, ...). The important notions of Kestra are : The flow:\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-01-1024x267.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-01-1024x267.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/kestra-01-1024x267.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1650,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/le-profiler-sql-de-visualvm\/","url_meta":{"origin":2007,"position":3},"title":"VisualVM SQL profiler SQL","author":"admin","date":"Tuesday April  4th, 2023","format":false,"excerpt":"A little while ago, I discovered the SQL profiler of VisualVM and I thought I should share it with you ;). VisualVM is a tool that provides a visual interface to display detailed information about applications running on a Java Virtual Machine (JVM). VisualVM is designed for use in development\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2023-04-03-14-17-25-1024x624.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2023-04-03-14-17-25-1024x624.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2023-04-03-14-17-25-1024x624.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1606,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/au-revoir-zenika-bonjour-kestra\/","url_meta":{"origin":2007,"position":4},"title":"(Fran\u00e7ais) Au revoir Zenika, bonjour Kestra","author":"admin","date":"Tuesday January 10th, 2023","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1731,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/optimisation-dindex-postgresql\/","url_meta":{"origin":2007,"position":5},"title":"PostgreSQL index optimization","author":"admin","date":"Tuesday August 22nd, 2023","format":false,"excerpt":"Some time ago, I worked on query execution time optimizations for PostgreSQL, I talk about it here: The VISUALVM SQL PROFILE. Kestra is a highly scalable data orchestration and scheduling platform that creates, executes, schedules, and monitors millions of complex pipelines. It's also the company I work for! The open\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/2007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=2007"}],"version-history":[{"count":6,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/2007\/revisions"}],"predecessor-version":[{"id":2040,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/2007\/revisions\/2040"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=2007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=2007"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=2007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}