¿Existe una función general de sustitución de cadenas similar a sl4fj?

3 minutos de lectura

avatar de usuario
kmccoy

Con sl4fj, si quiero construir un mensaje de cadena, hay un buen enfoque que utiliza sustituciones. Por ejemplo, podría ser algo como:

logger.info("Action {} occured on object {}.", objectA.getAction(), objectB);

Si se requieren más de unas pocas sustituciones, entonces es algo como:

logger.info("Action {} occured on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

Mi pregunta es: ¿hay alguna forma genérica de crear una cadena (y no solo un mensaje de registro slf4j)? Algo como:

String str = someMethod("Action {} occured on object {}.", objectA.getAction(), objectB);

o

String str = someMethod("Action {} occured on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

Si está en la biblioteca estándar de Java, ¿cuál sería ese “algún método”?

  • Gracias a aquellos con respuestas a continuación. Además, descubrí que esta pregunta ya se había hecho aquí: stackoverflow.com/questions/3114021. Lamento haber publicado un duplicado más o menos.

    – kmccoy

    20 de febrero de 2011 a las 23:42

  • ¿Responde esto a tu pregunta? ¿Hay alguna manera de construir una cadena Java usando una función de formato de estilo SLF4J?

    – Vestland

    16 de mayo de 2020 a las 7:14

Cadena.formato

String str = String.format("Action %s occured on object %s.",
   objectA.getAction(), objectB);

O

String str = String.format("Action %s occured on object %s with outcome %s.",
   new Object[]{objectA.getAction(), objectB, outcome});

También puede usar posiciones numéricas, por ejemplo, para cambiar los parámetros:

String str = String.format("Action %2$s occured on object %1$s.",
   objectA.getAction(), objectB);

avatar de usuario
Johan Sjoberg

Puedes usar Cadena.formato o FormatoMensaje.formato

P.ej,

MessageFormat.format("A sample value {1} with a sample string {0}", 
    new Object[] {"first", 1});

o simplemente

MessageFormat.format("A sample value {1} with a sample string {0}", "first", 1);

  • MessageFormat es muy versátil y poderoso, pero para reemplazos simples, String.format probablemente será más simple y menos restringido (por ejemplo, MessageFormat requiere que se dupliquen las comillas simples).

    – Kat

    21 de julio de 2014 a las 19:38

  • new Integer (1) reemplazado con solo 1 arriba, entonces también funcionará.

    – Tecnocrata

    15 de julio de 2015 a las 9:16

avatar de usuario
Balamurugan Muthiah

Si está buscando una solución en la que pueda reemplazar un montón de variables en una cadena con valores, puede usar StrSubstitutor.

 Map<String, String> valuesMap = new HashMap<>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target}.";
 StrSubstitutor sub = new StrSubstitutor(valuesMap);
 String resolvedString = sub.replace(templateString);

Sigue un patrón generalmente aceptado en el que se puede pasar un mapa con variables a valores junto con la cadena no resuelta y devuelve una cadena resuelta.

Sugeriría usar org.slf4j.helpers.MessageFormatter. Con su ayuda, se puede crear un método de utilidad que use exactamente el mismo estilo de formato que slf4j:

// utillity method to format like slf4j
public static String format(String msg, Object... objs) {
    return MessageFormatter.arrayFormat(msg, objs).getMessage();
}

// example usage
public static void main(String[] args) {
    String msg = format("This msg is {} like slf{}j would do. {}", "formatted", 4,
            new Exception("Not substituted into the message"));

    // prints "This msg is formatted like slf4j would do. {}"    
    System.out.println(msg); 
}

Nota: si el último objeto de la matriz es una excepción, no se sustituirá en el mensaje, al igual que con un registrador slf4j. La excepción sería accesible a través de MessageFormatter.arrayFormat(msg, objs).getThrowable().

Elijo envolver el Log4j2 Mensaje parametrizado que fue escrito originalmente para Lilith por Joern Huxhorn:

public static String format(final String messagePattern, Object... arguments) {
    return ParameterizedMessage.format(messagePattern, arguments);
}

Se centra en el formato del mensaje, a diferencia de SLF4J Formateador de mensajes que contiene procesamiento innecesario de Throwable.

Ver el Javadoc:

Maneja mensajes que consisten en una cadena de formato que contiene ‘{}’ para representar cada token reemplazable y los parámetros.

¿Ha sido útil esta solución?