I have the following JSON example below:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
I need to use MessageFormat to JUnit test this JSON example, but I get an invalid value because my Locale is not in english. If I change my Locale to english instead of brazilian portuguese I get an invalid description because the currency value is displayed in English.
Here's my code:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Locale;
Locale.setDefault(Locale.ENGLISH);
System.out.println(MessageFormat.format("""
'{'
"value": {0},
"description": "O valor é {0,number,currency}."
'}'
""", new BigDecimal(946.2)));
How can I format the value or the description in order to get the JSON as displayed above?
CodePudding user response:
Sure, no problem! But:
Locale.setDefaultis harsh! (for test it can be tolerable.... but i don't want to look up that bug..)- (I "don't like"
MessageFormat... it usesStringBufferinternally(Mr. performance killer & memory dumper).)
As long as you can handle the "complexity", it can be done like:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class MainSimple {
// Brazilian Locale:
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
// US number format:
private static final NumberFormat DEFAULT_NUMBER_FMT = NumberFormat.getNumberInstance(Locale.US);
public static void main(String[] args) {
// MessageFormat instance, with format (with 2! parameters) and Locale:
MessageFormat mainFmt = new MessageFormat("""
'{'
"value": {0},
"description": "O valor é {1,number,currency}. <-- trick 1 "
'}'
""", LOCALE_PT_BR);
final BigDecimal num = new BigDecimal(946.2);
// trick 2:
Object[] params = {DEFAULT_NUMBER_FMT.format(num), num};
// do it:
System.out.println(mainFmt.format(params));
}
}
Outline:
- Constants for:
- Brazilian (outer format) locale.
- US/Standard (inner) number format for custom (non brazilian) formatting/this particular number.
MessageFormathas a constructor with locale parameter! (we use that, and call it outer format/locale(mainFmt))- Int the format we "trick a little" and use 2 parameters:
{0}and{1,number,currency} - We trick on: Pass the first parameter as a (US-formatted number)
String, the second as had. (Object[] params = {DEFAULT_NUMBER_FMT.format(num), num}) - finally format (& print to out).
Prints:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
CodePudding user response:
This is a String.format solution with two inner (localized, customized) NumberFormatters:
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
public class OtherMain {
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
private static final NumberFormat DEFAULT_NUMBER_FMT
= NumberFormat.getNumberInstance(Locale.US);
private static final NumberFormat MY_SPECIAL_NUMBER_FMT
= NumberFormat.getCurrencyInstance(LOCALE_PT_BR);
static {
// this disables "thousands sperarator", we can adjust DEFAULT_NUMBER_FMT as well...
MY_SPECIAL_NUMBER_FMT.setGroupingUsed(false);
}
public static void main(String[] args) {
final BigDecimal num = new BigDecimal(99946.2);
System.out.format("""
{
"value": %s,
"description": "O valor é %s."
}
""",
DEFAULT_NUMBER_FMT.format(num),
MY_SPECIAL_NUMBER_FMT.format(num)
);
}
}
Prints:
{
"value": 99,946.2,
"description": "O valor é R$ 99946,20."
}
