Add @ToString to exclude null fields

2,583 views
Skip to first unread message

Lars

unread,
Mar 23, 2018, 2:43:03 PM3/23/18
to Project Lombok
Would love to see a parameter to exclude null fields. Would cut down on meaningless noise.

Marco Servetto

unread,
Mar 23, 2018, 2:51:08 PM3/23/18
to project...@googlegroups.com
I think this is a big NO. Even without entering in the merit of the
antipattern of having many fields constantly at null....
What is the limit/the next thing to exclude?
empty lists? empty strings? flag setted to false?

On 24 March 2018 at 07:43, Lars <northp...@gmail.com> wrote:
> Would love to see a parameter to exclude null fields. Would cut down on
> meaningless noise.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Project Lombok" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to project-lombo...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Martin Grajcar

unread,
Mar 23, 2018, 5:06:23 PM3/23/18
to project...@googlegroups.com
On Fri, Mar 23, 2018 at 7:50 PM, Marco Servetto <marco.s...@gmail.com> wrote:
I think this is a big NO. Even without entering in the merit of the
antipattern of having many fields constantly at null....
What is the limit/the next thing to exclude?
empty lists? empty strings? flag setted to false?

Actually, yes and yes and yes. 
Assuming we're speaking about toString, all these exclusions make sense.
Verbose toString is fine as long as you watch a single small object.
A stringified list can quickly get huge and spotting the relevant thing can get hard.
However, I can see that the corresponding settings can be complicated and hard to understand.

Maybe something like

@ToString 
class X {
   ... tons of fields

    @ToString.IgnorableTemplate
    private static final X EMPTY = new X():
}

could make sense, where all fields having a value equal to the value of the corresponding field in X.EMPTY would be ignored.

The annotation @ToString.IgnorableTemplate (allowed only once and only on a static final field of the same type) would switch this feature on.
The could be @ToString.AlwaysInclude to override it on a per field basis (if someone needed this).
This would only make sense when X.EMPTY never changes, but this is no big deal.

On 24 March 2018 at 07:43, Lars <northp...@gmail.com> wrote:
> Would love to see a parameter to exclude null fields. Would cut down on
> meaningless noise.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Project Lombok" group.
> To unsubscribe from this group and stop receiving emails from it, send an

> For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Project Lombok" group.
To unsubscribe from this group and stop receiving emails from it, send an email to project-lombok+unsubscribe@googlegroups.com.

Reinier Zwitserloot

unread,
Mar 27, 2018, 1:57:50 PM3/27/18
to Project Lombok
Customization #859185 requested of toString behaviour.

I think I have to give up on the dream of some sort of DSL that covers most of this stuff; how the heck would you put 'skip null fields' in a DSL anyway? It'd be as convoluted as regexes are.

If it's a flag on toString, it applies to all fields. One way out is to have a @ToString.Exclude and @ToString.Include annotation, where Include can also be put on methods, and IT can contain the noNull stuff too? Ugh, this feels utterly undiscoverable by your average lombok user.

Marco Servetto

unread,
Mar 27, 2018, 4:09:07 PM3/27/18
to project...@googlegroups.com
I think that toString is not too long anyway... so if you have any
specific need you can just implement it.
>>> > email to project-lombo...@googlegroups.com.
>>> > For more options, visit https://groups.google.com/d/optout.
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Project Lombok" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to project-lombo...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Project Lombok" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to project-lombo...@googlegroups.com.

Martin Grajcar

unread,
Mar 29, 2018, 10:30:58 PM3/29/18
to project...@googlegroups.com
On Tue, Mar 27, 2018 at 7:57 PM, Reinier Zwitserloot <rein...@gmail.com> wrote:
Customization #859185 requested of toString behaviour.

It'd be nice to have some poll for feature proposals.
 
I think I have to give up on the dream of some sort of DSL that covers most of this stuff; how the heck would you put 'skip null fields' in a DSL anyway? It'd be as convoluted as regexes are.

If it's a flag on toString, it applies to all fields. One way out is to have a @ToString.Exclude and @ToString.Include annotation, where Include can also be put on methods, and IT can contain the noNull stuff too? Ugh, this feels utterly undiscoverable by your average lombok user.

IMHO there's a simple solution: Mention @ToString.Include and @ToString.Exclude in the very first sentence of the Javadoc. Also add other such annotations, so that users get used to them.

It's pity that neither lambdas not method literals can't be used in annotations as something like @ToString.Include(onlyIf=Objects::nonNull) would be pretty cool. Having something like @ToString.Include(onlyIf=lombok.Condition.NonNull.class) is a bit ugly and not user-extensible.


Together with the possibility of including method, noNull would be enough at the expense of verbosity:

@ToString.Include(noNull=true)
private Object myField() {
    return whateverCondition(myField) ? null : myField;
}

Using this en masse would be crazy, but the typical case is that hardly any field needs customization.
However, when it does, then you have to write a manual toString() and have to deal with all fields.

Reinier Zwitserloot

unread,
Apr 4, 2018, 11:47:16 AM4/4/18
to Project Lombok
Okay, let's flesh this out some:

1. There will be @ToString.Include and @ToString.Exclude annotations.

2. @ToString.Include is like 'of' and exclude is like 'exclude', except.. you can put Include on a method. You can't put exclude on a method.

Problem 2A: What is the 'fieldname' of an @Include on a method? [I'm leaning to the answer: "Name of the method"]

Problem 2B: Should it be configurable? [I'm leaning: no]

Problem 2C: What if an @Include marked method has the same name as a field.. does that imply the field is then excluded unless also tagged with an include annotation, or should we just print both? [I'm leaning: Exclude by default, but I find this one an annoying wart and making the feature more complicated than I'd like]

Problem 2D: A common use case would presumably be to 'replace' a field's toString output with a modified form, and you can use the method to accomplish this. However, if you put @Include on a field, that implies it is the same as @ToString(of="foo"), which means all OTHER fields are NOT included. Therefore, to have the same behaviour for methods, putting a single @Include on a method then means all fields are excluded by default. However, unlike with of/fields that doesn't sound obvious to me. It also goes counter to common use-cases. That is, I expect that a common use case is that some field needs custom treatment for toString and therefore you want to exclude the field and include the method that returns an alternative string for the field. [Solution: I dunno.. perhaps instead of @ToString.Include we need a @ToString.Also, or a @ToString.Extra, or a @ToString.Replacement, or.... see, I don't like any of this. This is way too complicated!]

3. The Include annotation can offer some standard customizations. For starters, skipNull=true.

Problem 3A: Does it need any others right now? Perhaps 'include field name'? [I'm leaning: No, let's start here]

4. If using any @Include or @Exclude, you cannot use 'of' or 'exclude' on the annotation (lombok-generated compiler error).

Martin Grajcar

unread,
Apr 5, 2018, 3:36:01 PM4/5/18
to project...@googlegroups.com
On Wed, Apr 4, 2018 at 5:47 PM, Reinier Zwitserloot <rein...@gmail.com> wrote:
Okay, let's flesh this out some:

1. There will be @ToString.Include and @ToString.Exclude annotations.

Nice! 

2. @ToString.Include is like 'of' and exclude is like 'exclude', except.. you can put Include on a method. You can't put exclude on a method.

Sure.
 
Problem 2A: What is the 'fieldname' of an @Include on a method? [I'm leaning to the answer: "Name of the method"]

As the default, sure.
 
Problem 2B: Should it be configurable? [I'm leaning: no]

In the long run, I can imagine configuring names for both fields and method would be useful as they're often long and shortening them may be useful e.g., for logging.
 
Problem 2C: What if an @Include marked method has the same name as a field.. does that imply the field is then excluded unless also tagged with an include annotation, or should we just print both? [I'm leaning: Exclude by default, but I find this one an annoying wart and making the feature more complicated than I'd like]

I guess, exclude by default is best, otherwise, you'd get the same name (and possibly the same value) twice when "replacing" a field.
It can always be overridden in either case, but excluding is clearly more sensible.
 
Problem 2D: A common use case would presumably be to 'replace' a field's toString output with a modified form, and you can use the method to accomplish this. However, if you put @Include on a field, that implies it is the same as @ToString(of="foo"), which means all OTHER fields are NOT included.

This may be rather surprising, especially when @ToString.Include(...) gets used for customization only.
Actually, using a single Include for customization would force you to add Include to all fields, which feels very wrong.

I guess, we should be explicit instead, using @ToString(excludeByDefault=true) or better @ToString(of={}).
While combining inclusion/exclusion by both class level annotation arguments and field level annotations in general makes no sense,
of={} should be allowed together with Include.

Another idea: Allow @ToString.Exclude on the class level, too.
 
Therefore, to have the same behaviour for methods, putting a single @Include on a method then means all fields are excluded by default. However, unlike with of/fields that doesn't sound obvious to me. It also goes counter to common use-cases. That is, I expect that a common use case is that some field needs custom treatment for toString and therefore you want to exclude the field and include the method that returns an alternative string for the field. [Solution: I dunno.. perhaps instead of @ToString.Include we need a @ToString.Also, or a @ToString.Extra, or a @ToString.Replacement, or.... see, I don't like any of this. This is way too complicated!]

Yes, this all sounds way too complicated.
I'd suggest to always include all fields unless explicitly excluded (on field or class level).
Then using @ToString.Include without arguments and without such a class level exclusion is a no-op and should produce a warning.
This warning would make 
 
3. The Include annotation can offer some standard customizations. For starters, skipNull=true.

Problem 3A: Does it need any others right now? Perhaps 'include field name'? [I'm leaning: No, let's start here]

Agreed, skipNull is the most useful option.
I guess, skipEmpty comes just next to it.
Many fields of my entities are in fact nullable (as forced by Hibernate), but actually never null and initialized to an empty string.
Many of them are used only rarely and usually stay empty.
No way skipEmpty should imply skipNull as always only one value is the "normal" one.

Another idea for configuring this:
@ToString.Exclude(when={EMPTY, NULL})
but the default would be when=ALWAYS which doesn't make sense to combine with any other option (there should be no such enum member, if we wanted to an enum at here).
So I don't really like it, though it would work nicely on the class level, too.

4. If using any @Include or @Exclude, you cannot use 'of' or 'exclude' on the annotation (lombok-generated compiler error).

Unless you accept my proposal of being explicit by using of={}.
This would be the only exception, as other combinations might be too confusing.
Even this exception is still consistent with the general rule that field level annotations take precedence.

There should be an error if @ToString.Include or @ToString.Exclude gets used without @ToString.
Alternatively, @ToString could be implied (but I don't think saving a few chars is worth it).

I guess, I could make easily a reflection-based prototype (a method in a different class generating the same output as Lombok will) for this, when we clarify it a bit more. Would it be useful?

Reinier Zwitserloot

unread,
May 14, 2018, 4:09:19 PM5/14/18
to Project Lombok
It's live on the master branch.

seakleng

unread,
Jun 2, 2020, 12:26:20 AM6/2/20
to Project Lombok
Hello Marco! There are some cases we can't slice up our data fields like in the following iso8583.

Annotation 2020-06-02 100722.png


It's very valuable if we can a configuration to exclude those null values.



On Wednesday, March 28, 2018 at 3:09:07 AM UTC+7, Marco Servetto wrote:
I think that toString is not too long anyway... so if you have any
specific need you can just implement it.

On 28 March 2018 at 06:57, Reinier Zwitserloot <rein...@gmail.com> wrote:
> Customization #859185 requested of toString behaviour.
>
> I think I have to give up on the dream of some sort of DSL that covers most
> of this stuff; how the heck would you put 'skip null fields' in a DSL
> anyway? It'd be as convoluted as regexes are.
>
> If it's a flag on toString, it applies to all fields. One way out is to have
> a @ToString.Exclude and @ToString.Include annotation, where Include can also
> be put on methods, and IT can contain the noNull stuff too? Ugh, this feels
> utterly undiscoverable by your average lombok user.
>
> On Friday, March 23, 2018 at 10:06:23 PM UTC+1, Maaartin G wrote:
>>
>> On Fri, Mar 23, 2018 at 7:50 PM, Marco Servetto <marco....@gmail.com>
>>> > For more options, visit https://groups.google.com/d/optout.
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Project Lombok" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an
>>> For more options, visit https://groups.google.com/d/optout.
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Project Lombok" group.
> To unsubscribe from this group and stop receiving emails from it, send an

seakleng

unread,
Jun 2, 2020, 3:02:18 AM6/2/20
to Project Lombok
Hello Maaartin! May I know If the feature to exclude NULL on @ToString will be available?

Your response is really appreciated 😉

Martin Grajcar

unread,
Jun 2, 2020, 3:20:27 AM6/2/20
to project...@googlegroups.com
Hi seakleng,

I'm not a project maintainer and I haven't contributed for ages; I'm only trying to help by answering since the maintainers are very busy. There are tons of feature requests and implementing a lombok feature takes way more time than when doing similar stuff using e.g., reflection or annotation processing. AFAIK the project owners are currently busy with reworking the build script (it has to run with all javac and ecj versions since IIRC Java 6).

We still don't have a good syntax for this feature. Moreover, there are tons of similar and about equally good requests and implementing them all would blow up the feature set. It's not in the milestone, so I'm very skeptical.


--
You received this message because you are subscribed to the Google Groups "Project Lombok" group.
To unsubscribe from this group and stop receiving emails from it, send an email to project-lombo...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/project-lombok/1168b7df-a700-40e4-b857-8be7ea9c597a%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages