Заставьте ReflectionToStringBuilder пропустить поля с нулевыми значениями

Я должен напечатать значения объекта в файле журнала. Я использовал:

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

Но он также печатает нулевые значения, которые я не хочу включать, например:

Pojo @ 117d9a3 [id = 1,name = null, description = Манчестер Юнайтед,KEY=APP-KEY,secretKey=Alex ]

Как подавить нулевые значения от включения?

6 ответов

Более простое решение без подклассов - переопределить метод accept:

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();

}

Это дает дополнительное преимущество, которое вы можете использовать как угодно ToStringStyle вы хотите, и форматирование в противном случае идеально.

Вы должны предоставить свою собственную реализацию ToStringStyle. Как то так (не проверено!):

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);
        }
    }
}

Большая часть кода скопирована с MultiLineToStringStyle, так как это private а также final поэтому мы не можем продлить это. Реальная вещь происходит в append метод. Вот оригинал для справки:

    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);
    }

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)

Ответ @Christian Sporer (поднимите его голос), но он был изменен, чтобы стать утилитарным методом:

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();
  }
}

Начиная с 3.6, есть встроенный метод

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

Сигнатура метода:

      ReflectionToStringBuilder.toString(
   Object object, 
   ToStringStyle style, 
   boolean outputTransients, 
   boolean outputStatics, 
   boolean excludeNullValues, 
   Class<? super Object> reflectUpToClass)

Есть способ Создать новый вызов объекта ToStringStyle setNullText(String nullText) на этот объект с вашим собственным текстом, а затем передать этот объект ToStringStyle в конструктор ReflectionToStringBuilder учебный класс.

Другие вопросы по тегам