Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make ReflectionToStringBuilder skip fields with null values

I have to print object values in log file. I used:

ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE, true, true);

But it also prints null values which I don't want to include, for instance:

Pojo@117d9a3[id=1,name=null,description=Manchester United,KEY=APP-KEY,secretKey=Alex ]

How to suppress null values from being included?

like image 200
saravanan_jay Avatar asked May 10 '15 16:05

saravanan_jay


2 Answers

You have to provide your own ToStringStyle implementation. Something like this (untested!):

import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.builder.ToStringStyle;

public final class NotNullToStringStyle extends ToStringStyle {
    public static final ToStringStyle NOT_NULL_STYLE = new NotNullToStringStyle();

    private static final long serialVersionUID = 1L;

    /**
     * <p>Constructor.</p>
     *
     * <p>Use the static constant rather than instantiating.</p>
     */
    NotNullToStringStyle() {
        super();
        this.setContentStart("[");
        this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + "  ");
        this.setFieldSeparatorAtStart(true);
        this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]");
    }

    /**
     * <p>Ensure <code>Singleton</code> after serialization.</p>
     *
     * @return the singleton
     */
    private Object readResolve() {
        return NOT_NULL_STYLE;
    }

    @Override
    public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
        if (value != null) {
            appendFieldStart(buffer, fieldName);
            appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
            appendFieldEnd(buffer, fieldName);
        }
    }
}

Most of the code is copied from MultiLineToStringStyle, since it's private and final so we can't extend it. The real thing happens in the append method. Here is the original one for reference:

    public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
        appendFieldStart(buffer, fieldName);

        if (value == null) {
            appendNullText(buffer, fieldName);

        } else {
            appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
        }

        appendFieldEnd(buffer, fieldName);
    }
like image 131
ivant Avatar answered Nov 19 '22 18:11

ivant


A simpler solution without subclassing would be to override the accept method:

public String toStringWithAttributes() {

    Object myself = this;
    ReflectionToStringBuilder builder = new ReflectionToStringBuilder(
            this, ToStringStyle.SHORT_PREFIX_STYLE) {

            @Override
            protected boolean accept(Field field) {
                try {
                    return super.accept(field) && field.get(myself) != null;
                } catch (IllegalAccessException e) {
                    return super.accept(field);
                }
            }

    };

    return builder.toString();

}

This has the added benefit that you can use whatever ToStringStyle you want and the formatting is otherwise perfect.

like image 18
Christian Sporer Avatar answered Nov 19 '22 18:11

Christian Sporer