When using Jackson for deserialization of ZonedDateTime using ZoneId. Generated Equals does not return true because it compare date field with equals and not isEquals(ChronoLocalDate).
More details : https://stackoverflow.com/questions/25793628/java-8-zoneddatetime-not-equal-another-zoneddatetime
I bypassed the limitation using canEqual
@JsonDeserialize(builder = Example.ExampleBuilder.class)
@Getter
@Builder(setterPrefix = "with")
@EqualsAndHashCode
public class Example{
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@EqualsAndHashCode.Exclude private final ZonedDateTime date;
private final String description;
protected boolean canEqual(final Object other) {
Example example = (Example) other;
return ((date== null && example .date== null) || (date!= null && date.isEqual(example .date)));
}
@JsonPOJOBuilder
public static class ExampleBuilder {
}
}
Should be convenient to compare zoned date with isEquals and not Equals
In other words, you want Lombok to cheat and compare non-equal objects as equal. ;)
We could discuss whether ZonedDateTime.equals is right or wrong, but that's very far from Lombok. You mention Jackson and that could be the right place to fix it - once you get two non-equal objects, it's too late for anything but hacks.
I don't understand your canEqual. The method is meant to deal with different classes representing the same concept, while you deal with a single class.Your method is broken as it throws when fed with anything but Example.
However, there's a better solution. Instead of comparing date, you @Exclude it and @Include a method or two returning something to be compared instead. Based on isEqual :
@EqualsAndHashCode.Exclude
private final ZonedDateTime date;
@EqualsAndHashCode.Include
private final long dateEpochSecond() {
return date.toEpochSecond();
}
@EqualsAndHashCode.Include
private final long dateNano() {
return date.nano();
}
IMHO that's a good solution, however, it only works for your Example.date. Anywhere else, the normal equals get called. It can't changed in general (e.g., ZonedDateTime buried in other objects will always use their equals) and I don't think Lombok should incorporate a special treatment like it does for arrays. Reasons:
Disclaimer: I'm not a Lombok project owner.
Oh thanks for your answer, e@EqualsAndHashCode.Include is a cleaner way to resolve my problem.
In fact with date equals can have 2 definitions : object or time comparison.
Most helpful comment
In other words, you want Lombok to cheat and compare non-equal objects as equal. ;)
We could discuss whether
ZonedDateTime.equalsis right or wrong, but that's very far from Lombok. You mention Jackson and that could be the right place to fix it - once you get two non-equal objects, it's too late for anything but hacks.I don't understand your
canEqual. The method is meant to deal with different classes representing the same concept, while you deal with a single class.Your method is broken as it throws when fed with anything butExample.However, there's a better solution. Instead of comparing
date, you@Excludeit and@Includea method or two returning something to be compared instead. Based onisEqual:IMHO that's a good solution, however, it only works for your
Example.date. Anywhere else, the normalequalsget called. It can't changed in general (e.g.,ZonedDateTimeburied in other objects will always use theirequals) and I don't think Lombok should incorporate a special treatment like it does for arrays. Reasons:Disclaimer: I'm not a Lombok project owner.