使ReflectionToStringBuilder跳过具有空值的字段

时间:2015-05-10 16:53:00

标签: java apache-commons-lang

我必须在日志文件中打印对象值。我用过:

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

但它也打印了我不想包含的空值,例如:

  

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

如何禁止包含空值?

5 个答案:

答案 0 :(得分:15)

没有子类化的更简单的解决方案是覆盖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,格式是完美的。

答案 1 :(得分:4)

您必须提供自己的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复制的,因为它是privatefinal所以我们无法对其进行扩展。真实的事情发生在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);
    }

答案 2 :(得分:1)

@Christian Sporer's answer(赞成他),但被修改为可重用的util方法:

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 :(得分:0)

有一种方法使用您自己的文本在此对象上创建新的ToStringStyle对象调用setNullText(String nullText),然后将此ToStringStyle对象传递给ReflectionToStringBuilder类的构造函数。

答案 4 :(得分:0)

Apache commons-lang3 提供了开箱即用的实现:

ReflectionToStringBuilder.toString(new Pojo(), ToStringStyle.DEFAULT_STYLE, true, 假,,空)

输出符合要求:

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

使用:
public static String toString( 最终的 T 对象,最终的 ToStringStyle 样式,最终的布尔值 outputTransients, final boolean outputStatics,final boolean excludeNullValues,final ClassreflectUpToClass)