Back when the first JSON escape method was written, I think it was
based on the JSON RFC. Looks like it's been modified a bit since then,
so I'm not sure if it's expected behavior or not.

On Tue, 7 Apr 2020 at 15:18, Volkan Yazıcı <volkan.yaz...@gmail.com> wrote:
>
> Hello,
>
> There are a couple of concerns I want to share regarding the available
> JSON quoting options in the core. I would appreciate your feedback on
> them.
>
> 1. My first concern is... There are 2 competing JSON quoting
>    implementations in the core:
>
>    - JsonUtils.quoteAsString(CharSequence, StringBuilder)
>    - StringBuilders.escapeJson(StringBuilder, int)
>
>    escapeJson() is our homegrown solution and quoteAsString() is the one
>    we borrowed from Jackson. I am in favor of marking the first as deprecated,
>    removing its implementation, and directing it to quoteAsString(). (Jackson
>    clone is significantly faster.)
>
> 2. JsonUtils.quoteAsString() uses ThreadLocals without honoring the
>     ENABLE_THREADLOCALS flag.
>
> 3. JsonUtils.quoteAsString() doesn't really need TLA at all; it can just 
> receive
>    a char[6] argument, where the call site can deal with the caching of that
>    buffer at its own will.
>
> 4. escapeJson() produces slightly different results compared to
>    quoteAsString() and Jackson. For demonstration purposes, I've
>    created the following setup:
>
> @Test
> public void test_quoting() throws Exception {
>     final ObjectMapper objectMapper = new ObjectMapper();
>     final StringBuilder stringBuilder = new StringBuilder();
>     final SoftAssertions assertions = new SoftAssertions();
>     for (char c = Character.MIN_VALUE;; c++) {
>
>         final String s = "" + c;
>         final String jacksonEncodedJson =
>                 objectMapper.writeValueAsString(s);
>
>         stringBuilder.setLength(0);
>         JsonUtils.quoteAsString(s, stringBuilder);
>         final String quoteAsStringEncodedJson =
>                 '"' + stringBuilder.toString() + '"';
>
>         assertions
>                 .assertThat(quoteAsStringEncodedJson)
>                 .as("c=%d (quoteAsString)", (int) c)
>                 .isEqualTo(jacksonEncodedJson);
>
>         stringBuilder.setLength(0);
>         stringBuilder.append(c);
>         StringBuilders.escapeJson(stringBuilder, 0);
>         final String escapeJsonEncodedJson =
>                 '"' + stringBuilder.toString() + '"';
>
>         assertions
>                 .assertThat(escapeJsonEncodedJson)
>                 .as("c=%d (escapeJson)", (int) c)
>                 .isEqualTo(jacksonEncodedJson);
>
>         if (c == Character.MAX_VALUE) {
>             break;
>         }
>
>     }
>     assertions.assertAll();
> }
>
>    This is the output I get:
>
>    The following 33 assertions failed:
>    1) [c=127 (escapeJson)] expected:<""[ ]""> but was:<""[\u007F]"">
>    2) [c=128 (escapeJson)] expected:<""[?]""> but was:<""[\u0080]"">
>    3) [c=129 (escapeJson)] expected:<""[?]""> but was:<""[\u0081]"">
>    4) [c=130 (escapeJson)] expected:<""[?]""> but was:<""[\u0082]"">
>    5) [c=131 (escapeJson)] expected:<""[?]""> but was:<""[\u0083]"">
>    6) [c=132 (escapeJson)] expected:<""[?]""> but was:<""[\u0084]"">
>    7) [c=133 (escapeJson)] expected:<""[…]""> but was:<""[\u0085]"">
>    8) [c=134 (escapeJson)] expected:<""[?]""> but was:<""[\u0086]"">
>    9) [c=135 (escapeJson)] expected:<""[?]""> but was:<""[\u0087]"">
>    10) [c=136 (escapeJson)] expected:<""[?]""> but was:<""[\u0088]"">
>    11) [c=137 (escapeJson)] expected:<""[?]""> but was:<""[\u0089]"">
>    12) [c=138 (escapeJson)] expected:<""[?]""> but was:<""[\u008A]"">
>    13) [c=139 (escapeJson)] expected:<""[?]""> but was:<""[\u008B]"">
>    14) [c=140 (escapeJson)] expected:<""[?]""> but was:<""[\u008C]"">
>    15) [c=141 (escapeJson)] expected:<""[?]""> but was:<""[\u008D]"">
>    16) [c=142 (escapeJson)] expected:<""[?]""> but was:<""[\u008E]"">
>    17) [c=143 (escapeJson)] expected:<""[?]""> but was:<""[\u008F]"">
>    18) [c=144 (escapeJson)] expected:<""[?]""> but was:<""[\u0090]"">
>    19) [c=145 (escapeJson)] expected:<""[?]""> but was:<""[\u0091]"">
>    20) [c=146 (escapeJson)] expected:<""[?]""> but was:<""[\u0092]"">
>    21) [c=147 (escapeJson)] expected:<""[?]""> but was:<""[\u0093]"">
>    22) [c=148 (escapeJson)] expected:<""[?]""> but was:<""[\u0094]"">
>    23) [c=149 (escapeJson)] expected:<""[?]""> but was:<""[\u0095]"">
>    24) [c=150 (escapeJson)] expected:<""[?]""> but was:<""[\u0096]"">
>    25) [c=151 (escapeJson)] expected:<""[?]""> but was:<""[\u0097]"">
>    26) [c=152 (escapeJson)] expected:<""[?]""> but was:<""[\u0098]"">
>    27) [c=153 (escapeJson)] expected:<""[?]""> but was:<""[\u0099]"">
>    28) [c=154 (escapeJson)] expected:<""[?]""> but was:<""[\u009A]"">
>    29) [c=155 (escapeJson)] expected:<""[?]""> but was:<""[\u009B]"">
>    30) [c=156 (escapeJson)] expected:<""[?]""> but was:<""[\u009C]"">
>    31) [c=157 (escapeJson)] expected:<""[?]""> but was:<""[\u009D]"">
>    32) [c=158 (escapeJson)] expected:<""[?]""> but was:<""[\u009E]"">
>    33) [c=159 (escapeJson)] expected:<""[?]""> but was:<""[\u009F]"">
>
>    I am not a JSON expert, but I find this worrying. Would anybody
>    provide some further feedback on what is going on here, please?
>
> Kind regards.



-- 
Matt Sicker <boa...@gmail.com>

Reply via email to