Do you know pretty way to log you objects in json format?

225 Views Asked by At

When use spring boot, from time to time I need to log my objects like UserInfo, Person and another to log in json format

If I log just to put my object, logs looks like User@3242 (with hash code)

So I tried any ways to solve this issue, but every of this have many disadvantages

1)

log.info("hello {}", objectMapper.writeValueAsString(user))

but this way is not handy because I need try catch, user may cause npe, and I can forget to user objectMapper

  1. crete console appender for json logs

    true yyyy-MM-dd' 'HH:mm:ss.SSS true %d{yyyy-MM-dd HH:mm:ss} %-5p %m%n
     <root name="standard" level="info">
         <appender-ref ref="stdout"/>
     </root>
     <logger name="jsonLogger" level="info">
         <appender-ref ref="json"/>
     </logger>
    

but this way just transforms my logs in json but user put in message filed and write like simple toString()

  1. Override toString() on every object using ObjectMapper but this way is increas overhead of write new code

Do you know another handy way to log in json just my custom objects?

1

There are 1 best solutions below

2
DevilsHnd - 退した On

You can of course override the User class toString() method and return the instance of of the current user object as string in the format you want, for example:

Simple example of a User class:

public class User {

    private String name;
    private String password;

    public User() {}

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    // Custom toString() method:
    @override
    public String toString() {
        StringBuilder sb = new StringBuilder("");
        sb.append("User Object Instance: -> User Name: ");
        sb.append(this.name).append("  -  User Password: ");
        sb.append(this.password); 

        return sb.toString();
    }
}

How you might use:

log.info("hello {}", user.toString());

The custom toString() method within the User class should return something like:

"User Object Instance: -> User Name: Fred Flintstone  -  User Password: MyPassword"

Change the toString() method code to return whatever format you want.

If however, you actually want to add a JSON or XML Compact-Print or Pretty-Print string to the log and you don't mind adding some Jackson API's to your project and add the following methods to your User class (be sure to read the JavaDoc for each method):

To produce a JSON String:

/**
 * This method utilizes the following Jackson API jar files: 
 * Tested with:<pre>
 *     jackson-dataformat-xml-2.16.1.jar
 *     jackson-core-2.16.1.jar
 *     jackson-databind-2.16.1.jar
 *     jackson-annotations-2.16.1.jar
 *     stax2-api-4.2.1.jar
 *     woodstox-core-6.5.1.jar
 * </pre>
 * 
 * Converts this instance of User to a JSON string in either Compact-Print 
 * or in default Pretty-Print.<br>
 * 
 * @param asCompactPrint (boolean - varArg - Optional) By default Compact-
 * Print is false which tells the method to create the JSON string in a 
 * Pretty-Print format. If boolean <b>true</b> is supplied then a Compact-
 * Print format JSON string is returned.
 * 
 * @return (String) The current Object instance converted to a JSON String.
 */
public String toJSON (boolean... asCompactPrint) {
    boolean compact = false;
    if (asCompactPrint.length > 0) {
        compact = asCompactPrint[0];
    }

    String resultString = "";
    
    try {
        com.fasterxml.jackson.databind.ObjectMapper mapper
            = new com.fasterxml.jackson.databind.ObjectMapper();
        if (compact) {
            // Java object to Compact-Print JSON string:
            resultString = mapper.writeValueAsString(this);
        }
        else {
            // Java object to Pretty-Print JSON string:
            resultString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
        }
    }
    catch (com.fasterxml.jackson.core.JsonProcessingException ex) {
        System.err.println(ex);
    }
    
    return resultString;
}

then try something like this:

For Pretty-Print:

log.info("hello {}", user.toJSON()); 

For Compact-Print:

log.info("hello {}", user.toJSON(true)); 

To produce a XML String:

/**
 * This method utilizes the following Jackson API jar files:
 * Tested with:<pre>
 *     jackson-dataformat-xml-2.16.1.jar
 *     jackson-core-2.16.1.jar
 *     jackson-databind-2.16.1.jar
 *     jackson-annotations-2.16.1.jar
 *     stax2-api-4.2.1.jar
 *     woodstox-core-6.5.1.jar
 * </pre>
 * 
 * Converts this instance of User to a XML string in either Compact-Print 
 * or in default Pretty-Print.<br>
 * 
 * @param asCompactPrint (boolean - varArg - Optional) By default Compact-
 * Print is false which tells the method to create the XML string in a 
 * Pretty-Print format. If boolean <b>true</b> is supplied then a Compact-
 * Print format XML string is returned.
 * 
 * @return (String) The current Object instance converted to a XML String.
 */
public String toXML(boolean... asCompactPrint) {
    boolean compactPrint = false;
    if (asCompactPrint.length > 0) {
        compactPrint = asCompactPrint[0];
    }

    String resultString = "";
    try {
        com.fasterxml.jackson.dataformat.xml.XmlMapper xmlMap = 
                        new com.fasterxml.jackson.dataformat.xml.XmlMapper();
        
        if (!compactPrint) {
            resultString = xmlMap.writerWithDefaultPrettyPrinter().writeValueAsString(this);
        }
        else {
            resultString = xmlMap.writeValueAsString(this);
        }
    }
    catch (JsonProcessingException ex) {
        System.err.println(ex);
    }

    return resultString;
}

then try something like this:

For Pretty-Print:

log.info("hello {}", user.toXML()); 

For Compact-Print:

log.info("hello {}", user.toXML(true));