Is there a general string substitution function similar to sl4fj?

Java

Java Problem Overview


With sl4fj if I want to construct a string message there is a nice approach which makes use of substitutions. For instance, it might be something like:

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

If there are more than a few substitutions required then it is something like:

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

My question is: Is there a generic way for me to create a string (and not just a slf4j log message)? Something like:

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

or

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

If it is in the standard Java library, what would that "someMethod" be?

Java Solutions


Solution 1 - Java

String.format

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

Or

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

You can also use numeric positions, for example to switch the parameters around:

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

Solution 2 - Java

You can use String.format or MessageFormat.format

E.g.,

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

or simply

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

Solution 3 - Java

If you are looking for a solution where you can replace a bunch of variables in a String with values, you can use 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);

It follows a generally accepted pattern where one can pass a map with variables to values along with the unresolved String and it returns a resolved String.

Solution 4 - Java

I would suggest to use org.slf4j.helpers.MessageFormatter. With the help of it one can create a utillity method that uses the exact same formatting style as 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); 
}

Note: If the last object in the array is an Exception it will not be substituted in the message, just like with an slf4j logger. The Exception would be accessible via MessageFormatter.arrayFormat(msg, objs).getThrowable().

Solution 5 - Java

I choose wrap the Log4j2 ParameterizedMessage which was originally written for Lilith by Joern Huxhorn:

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

It is focus on message format, unlike SLF4J MessageFormatter which contains unnecessary processing of Throwable.

See the Javadoc:

> Handles messages that consist of a format string containing '{}' to represent each replaceable token, and the parameters.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkmccoyView Question on Stackoverflow
Solution 1 - JavaThe Scrum MeisterView Answer on Stackoverflow
Solution 2 - JavaJohan SjöbergView Answer on Stackoverflow
Solution 3 - JavaBalamurugan MuthiahView Answer on Stackoverflow
Solution 4 - JavaPeteView Answer on Stackoverflow
Solution 5 - JavazhoujiView Answer on Stackoverflow