Tengo el siguiente ejemplo JSON a continuación:
{ "value": 946.2, "description": "O valor é R$ 946,20." }Necesito usar MessageFormat para probar JUnit este ejemplo de JSON, pero obtengo un valor no válido porque mi Locale no está en inglés. Si cambio mi configuración regional a inglés en lugar de portugués brasileño, obtengo una descripción no válida porque el valor de la moneda se muestra en inglés.
Aquí está mi código:
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)));¿Cómo puedo formatear el valor o la descripción para obtener el JSON como se muestra arriba?
¡Claro, no hay problema! Pero:
Locale.setDefault es duro! (para la prueba, puede ser tolerable... pero no quiero buscar ese error...)MessageFormat ... usa StringBuffer internamente (Mr. Performance Killer & Memory dumper)).Siempre que pueda manejar la "complejidad", se puede hacer como:
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)); } }Esquema:
MessageFormat tiene un constructor con parámetro de configuración regional ! ( usamos eso , y lo llamamos formato externo/local ( mainFmt )){0} y {1,number,currency}String (número con formato de EE. UU.), el segundo como lo había hecho. ( Object[] params = {DEFAULT_NUMBER_FMT.format(num), num} )Huellas dactilares:
{ "value": 946.2, "description": "O valor é R$ 946,20." }Esta es una solución String.format con dos NumberFormat ters internos (localizados, personalizados):
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) ); } }Huellas dactilares:
{ "value": 99,946.2, "description": "O valor é R$ 99946,20." }