13

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?

zb226
  • 9,586
  • 6
  • 49
  • 79
saravanan_jay
  • 145
  • 1
  • 5

6 Answers6

18

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.

5

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);
    }
ivant
  • 3,909
  • 1
  • 25
  • 39
  • If its not extends,how do i implement.I tried remove final also.Its not work. Pls explain me how do i implement this scenario. – saravanan_jay May 12 '15 at 04:14
  • The class `NotNullToStringStyle` already implements this. You just have to use it like this: `ReflectionToStringBuilder.toString(this, NotNullToStringStyle.NOT_NULL_STYLE, true, true)` – ivant May 12 '15 at 06:17
  • the main benefit of this approach is code reuse across several POJOs. The main drawback is that you're tied to a single style, while, if you extend `ReflectionToStringBuilder`, you can skip nulls while using whichever style. – Clint Eastwood Jan 17 '19 at 17:36
5

Out of the box implementation exists from Apache commons-lang3:

ReflectionToStringBuilder.toString(new Pojo(), ToStringStyle.DEFAULT_STYLE, true, false, true, null)

Output is as requested:

general.Pojo@3532ec19[description=Manchester,id=1]

Using:
public static String toString( final T object, final ToStringStyle style, final boolean outputTransients, final boolean outputStatics, final boolean excludeNullValues, final Class<? super T> reflectUpToClass)

Liran
  • 144
  • 2
  • 6
2

@Christian Sporer's answer (go upvote him), but modified to be a reusable util method:

public class ToStringUtil {
  public static String toStringWithAttributes(Object ofInterest, ToStringStyle style) { 
    ReflectionToStringBuilder builder = new ReflectionToStringBuilder(ofInterest, style) { 
      @Override
      protected boolean accept(Field field) {
        try { return super.accept(field) && field.get(ofInterest) != null; }
        catch (IllegalAccessException e) { return super.accept(field); }
      }
    };
    return builder.toString();
  }
}
Marquee
  • 1,776
  • 20
  • 21
0

Since 3.6, there is a built in method

ReflectionToStringBuilder.toString(this, ToStringStyle.DEFAULT_STYLE,false,false,true,null);

The method signature is:

ReflectionToStringBuilder.toString(
   Object object, 
   ToStringStyle style, 
   boolean outputTransients, 
   boolean outputStatics, 
   boolean excludeNullValues, 
   Class<? super Object> reflectUpToClass)
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
-1

There is a way Create new ToStringStyle object call setNullText(String nullText) on this object with your own text, then pass this ToStringStyle object into constructor of the ReflectionToStringBuilder class.

Kiran Kumar
  • 1,033
  • 7
  • 20