Differences in excluded fields in objects of a collection cause state of collection diff to be changed
luispollo opened this issue · 3 comments
Hi Daniel,
First of all, thanks a lot for the awesome library! We've been using it in open-source Spinnaker for over a year now with great results.
I think I may have run into a corner case. We are configuring a differ in Kotlin like so:
val differ: ObjectDiffer = ObjectDifferBuilder
.startBuilding()
.apply {
comparison().ofType(Instant::class.java).toUseEqualsMethod()
inclusion().resolveUsing(object : InclusionResolver {
override fun getInclusion(node: DiffNode): Inclusion =
if (node.getPropertyAnnotation<ExcludedFromDiff>() != null) EXCLUDED else INCLUDED
override fun enablesStrictIncludeMode() = false
})
}
.build()This allows us to use a @ExcludedFromDiff annotation to exclude unwanted properties from the diff. This normally works just fine, but I came across a case where, if the objects with excluded fields are part of a collection, and I compare the collection itself, the differ reports a state of CHANGED instead of the expected UNTOUCHED.
For example, this comparison reports UNTOUCHED:
data class MyObject(
@get:ExcludedFromDiff
val prop: String
)
val base = MyObject("test")
differ.compare(base, base.copy(prop = "whatever"))But this comparison reports CHANGED:
differ.compare(setOf(base), setOf(base.copy(prop = "whatever")))I've tried my best to debug the issue, but failed. If you have any insights and could at least confirm whether you think this might be a bug and whether there's any workaround in version 0.95, that would be greatly appreciated!
Cc: @robfletcher, @lorin
比较两个集合对象, 会执行de.danielbechler.diff.differ.CollectionDiffer比较器逻辑:
- 遍历working集合中的每个元素, 如果不存在于base集合中, 则认为working集合新增了元素
- 遍历base集合中的每个元素, 如果不存在于working集合中, 则认为working集合删除了元素
- 元素同时存在于两个集合中, 才会继续比较每个属性的值, 这种情况你的配置才会生效
关键代码:
de.danielbechler.diff.differ.CollectionDiffer#compareInternally
de.danielbechler.diff.access.CollectionItemAccessor#get
de.danielbechler.diff.identity.EqualsIdentityStrategy#equals
判断集合中元素是否相同, 默认调用对象的equals方法, 基于此, 提供两种解决办法:
- 可以重写数据类的
equals和hashCode方法, 忽略添加ExcludedFromDiff注解的字段 - 自定义并配置
IdentityStrategy