patrick BAK
patrick BAK

Reputation: 341

How to skip null field with lombok @ToString

I found with no succes the simple way to use lombok @toString with the skip null field behaviour.

I think create my own toString function for all function using the aspect programmation. Like that i can chek all null field and skip that.

But it is the good practice, or lombok @toString has one option to do that simply?

Best Regards

Upvotes: 19

Views: 14764

Answers (6)

Zhenia Ho
Zhenia Ho

Reputation: 1

I found the best way for me. How to hide rows where values are null, 0? Guava doesn't help me because Guava interprets an int as string, but 0 value, it isn't a null value, so I couldn't hide rows if the row is an int.

My way:

public static void appendIfStringNotNull(StringBuilder stringBuilder, String msgForAppend ,String field) {

if (field != null && !field.isEmpty()) {

    stringBuilder.append(msgForAppend).append(field).append(", ");

}

}

public static void appendIfIntegerNotNull(StringBuilder stringBuilder, String msgForAppend ,Integer field) {

if (field != null && field != 0) {

    stringBuilder.append(msgForAppend).append(field).append(", ");

}

}

public String toString() {

StringBuilder sb = new StringBuilder();

Building.appendIfStringNotNull(sb, "Place: ", place);

Building.appendIfIntegerNotNull(sb, "Height: ", height);

Building.appendIfIntegerNotNull(sb, "Width: ", width);

return sb.length() > 0 ? sb.substring(0, sb.length() - 2) : "";

}

Upvotes: 0

Julien Kronegg
Julien Kronegg

Reputation: 5261

I could not find a Lombok way of doing it, so I postprocess the generated String using the following method:

/**
 * Removes the null values from String generated through the @ToString annotation.
 * For example:
 * - replaces:  AddressEntity(id=null, adrType=null, adrStreet=null, adrStreetNum=null, adrComplement=null, adrPoBox=null, adrNip=null, adrCity=city, adrCountry=null, adrNameCorresp=nameCorresp, adrSexCorresp=null, adrSource=null, adrSelectionReason=null, validityBegin=null, validityEnd=null, lastModification=null, dataQuality=null)
 * - by:        AddressEntity(adrCity=city, adrNameCorresp=nameCorresp)
 * Note: does not support tricky attribute content such as "when, x=null, it fails".
 * @param lombokToString a String generated by Lombok's @ToString method
 * @return a string without null values
 */
public static String removeToStringNullValues(String lombokToString) {
    //Pattern
    return lombokToString != null ? lombokToString
            .replaceAll("(?<=(, |\\())[^\\s(]+?=null(?:, )?", "")
            .replaceFirst(", \\)$", ")") : null;
}

Note that tricky object attributes such as "when, x=null, it fails" are not supported (but that's not an issue for my use-case). I could have used https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html to generate the "toString" content, but I wanted to reuse the field exclusion logic behind Lombok @ToString(excludes="myExcludedField").

[edited]

Your class could also implement an interface with a default method:

public interface ToStringWithoutNullValuesProvider {
    default String toStringWithoutNullValues() {
        return removeToStringNullValues(toString()); // see method above
    }
}

So your class could be something like:

@ToString(excludes="city")
public class AddressEntity implements ToStringWithoutNullValuesProvider {
    String city;
    String country;
}

then you can call myAddressEntity.toStringWithoutNullValues() to get the String representation without null values, but still having the code generated by Lombok (=without using introspection).

Upvotes: 2

Sergii Poltorak
Sergii Poltorak

Reputation: 11

With Guava:

@Override
public String toString() {
    return MoreObjects.toStringHelper(this)
            .omitNullValues()
            .add("fieldA", fieldA)
            .add("fieldB", fieldB)
            .toString();
}

Upvotes: 1

bratan
bratan

Reputation: 3487

Not Lombok-y but this helped me, while waiting patiently for Lombok to include this feature in...

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

  @Override
  public String toString() {
    ReflectionToStringBuilder rtsb = new ReflectionToStringBuilder(this);
    rtsb.setExcludeNullValues(true);
    return rtsb.toString();
  }

Upvotes: 4

Udisuarez
Udisuarez

Reputation: 47

You can override toString method like below

public class MyClass{

field a;
field b;

@Override
public String toString() {
    Field[] fields = MyClass.class.getDeclaredFields();
    String res = "";
    for(int x = 0; x < fields.length; x++){
        try {
            res += ( fields[x].get(this)) != null ? fields[x].getName() + "="+ (fields[x].get(this).toString()) + "," : "";
        } catch (Exception ex) {
            
        } 
    }
    return res;
}

Upvotes: 3

Pushkar Adhikari
Pushkar Adhikari

Reputation: 510

It's an open issue on Lombok, so it's not part of implementation yet. see #1297.

Upvotes: 7

Related Questions