diff --git a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java index d40a838a3..0b4d7e597 100644 --- a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java @@ -300,6 +300,64 @@ public class ReflectionToStringBuilder extends ToStringBuilder { return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics) .toString(); } + + /** + *
+ * Builds a toString
value through reflection.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ * If the outputTransients
is true
, transient fields will be output, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object.
+ *
+ * If the outputStatics
is true
, static fields will be output, otherwise they are
+ * ignored.
+ *
+ * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
+ * java.lang.Object
.
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
toString
to create, may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ * @param excludeNulls
+ * whether to exclude fields whose values are null
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is null
+ *
+ * @see ToStringExclude
+ * @since 2.1
+ */
+ public static "password"
.
@@ -483,6 +546,38 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
this.setAppendTransients(outputTransients);
this.setAppendStatics(outputStatics);
}
+
+ /**
+ * Constructor.
+ *
+ * @param toString
for
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param buffer
+ * the StringBuffer
to populate, may be null
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ * @param excludeNullValues
+ * whether to exclude fields who value is null
+ * @since 2.1
+ */
+ public Field
.
@@ -547,7 +642,9 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
// Warning: Field.get(Object) creates wrappers objects
// for primitive types.
final Object fieldValue = this.getValue(field);
- this.append(fieldName, fieldValue);
+ if(!excludeNullValues || fieldValue != null){
+ this.append(fieldName, fieldValue);
+ }
} catch (final IllegalAccessException ex) {
//this can't happen. Would get a Security exception
// instead
@@ -619,6 +716,17 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
public boolean isAppendTransients() {
return this.appendTransients;
}
+
+ /**
+ * + * Gets whether or not to append fields whose values are null. + *
+ * + * @return Whether or not to append fields whose values are null. + */ + public boolean isExcludeNullValues() { + return this.excludeNullValues; + } /** *@@ -658,6 +766,18 @@ public class ReflectionToStringBuilder extends ToStringBuilder { public void setAppendTransients(final boolean appendTransients) { this.appendTransients = appendTransients; } + + /** + *
+ * Sets whether or not to append fields whose values are null. + *
+ * + * @param excludeNullValues + * Whether or not to append fields whose values are null. + */ + public void setExcludeNullValues(final boolean excludeNullValues) { + this.excludeNullValues = excludeNullValues; + } /** * Sets the field names to exclude. diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java new file mode 100644 index 000000000..be368d664 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java @@ -0,0 +1,99 @@ +package org.apache.commons.lang3.builder; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class ReflectionToStringBuilderExcludeNullValuesTest { + + class TestFixture{ + private Integer testIntegerField; + private String testStringField; + + public TestFixture(Integer a, String b){ + this.testIntegerField = a; + this.testStringField = b; + } + } + + private static final String INTEGER_FIELD_NAME = "testIntegerField"; + private static final String STRING_FIELD_NAME = "testStringField"; + private final TestFixture BOTH_NON_NULL = new TestFixture(0, "str"); + private final TestFixture FIRST_NULL = new TestFixture(null, "str"); + private final TestFixture SECOND_NULL = new TestFixture(0, null); + private final TestFixture BOTH_NULL = new TestFixture(null, null); + + @Test + public void test_NonExclude(){ + //normal case= + String toString = ReflectionToStringBuilder.toString(BOTH_NON_NULL, null, false, false, false, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + //make one null + toString = ReflectionToStringBuilder.toString(FIRST_NULL, null, false, false, false, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + //other one null + toString = ReflectionToStringBuilder.toString(SECOND_NULL, null, false, false, false, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + //make the both null + toString = ReflectionToStringBuilder.toString(BOTH_NULL, null, false, false, false, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + } + + @Test + public void test_excludeNull(){ + + //test normal case + String toString = ReflectionToStringBuilder.toString(BOTH_NON_NULL, null, false, false, true, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + //make one null + toString = ReflectionToStringBuilder.toString(FIRST_NULL, null, false, false, true, null); + assertFalse(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + //other one null + toString = ReflectionToStringBuilder.toString(SECOND_NULL, null, false, false, true, null); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertFalse(toString.contains(STRING_FIELD_NAME)); + + //both null + toString = ReflectionToStringBuilder.toString(BOTH_NULL, null, false, false, true, null); + assertFalse(toString.contains(INTEGER_FIELD_NAME)); + assertFalse(toString.contains(STRING_FIELD_NAME)); + } + + @Test + public void test_ConstructorOption(){ + ReflectionToStringBuilder builder = new ReflectionToStringBuilder(BOTH_NON_NULL, null, null, null, false, false, false); + builder.setExcludeNullValues(true); + assertTrue(builder.isExcludeNullValues()); + + String toString = builder.toString(); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + builder = new ReflectionToStringBuilder(FIRST_NULL, null, null, null, false, false, true); + toString = builder.toString(); + assertFalse(toString.contains(INTEGER_FIELD_NAME)); + assertTrue(toString.contains(STRING_FIELD_NAME)); + + builder = new ReflectionToStringBuilder(SECOND_NULL, null, null, null, false, false, true); + toString = builder.toString(); + assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertFalse(toString.contains(STRING_FIELD_NAME)); + + builder = new ReflectionToStringBuilder(BOTH_NULL, null, null, null, false, false, true); + toString = builder.toString(); + assertFalse(toString.contains(INTEGER_FIELD_NAME)); + assertFalse(toString.contains(STRING_FIELD_NAME)); + } + +}