Search code examples
javajsonescapingjava-17messageformat

How to escape json-stylished String to work with MessageFormat?


I'm using and the following code snippet breaks because MessageFormat gets JSON symbols such as { and } and interprets them as its own formatters preventing the String to be formatted:

import java.math.BigDecimal;
import java.text.MessageFormat;

public class Test {

    public static void main(final String[] args) {
        System.out.println(MessageFormat.format("""
                {
                    "a": "{0}",
                 {
                  "b": "{0}"
                  "c": "{0}"
                  "d": {1,number,#.##}
                 }
                }""", "Test", new BigDecimal("10.123")));
    }
}

Here's the stack trace:

Exception in thread "main" java.lang.IllegalArgumentException: can't parse argument number: 
    "a": "{0}"
    at java.base/java.text.MessageFormat.makeFormat(MessageFormat.java:1454)
    at java.base/java.text.MessageFormat.applyPattern(MessageFormat.java:492)
    at java.base/java.text.MessageFormat.<init>(MessageFormat.java:371)
    at java.base/java.text.MessageFormat.format(MessageFormat.java:860)
    at Test.main(Test.java:9)
Caused by: java.lang.NumberFormatException: For input string: "
    "a": "{0}""
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:654)
    at java.base/java.lang.Integer.parseInt(Integer.java:786)
    at java.base/java.text.MessageFormat.makeFormat(MessageFormat.java:1452)
    ... 4 more

What's the correct way to escape these symbols in order to MessageFormat actually formats the String?


Solution

  • Nothing should change in that syntax in Java 17 since the MessageFormat is known from Java 7. As cited here in the past: Accepted answer for Question #1187093

    Within a String, a pair of single quotes can be used to quote any arbitrary characters except single quotes. For example, pattern string "'{0}'" represents string "{0}", not a FormatElement.