Структурное равенство зависит от местоположения определения класса случая после десериализации - PullRequest
4 голосов
/ 28 апреля 2019

Почему на сравнение структурного равенства после десериализации с экземпляром класса случая влияет расположение определения класса случая внутри или вне другого класса.Например, утверждение в следующем фрагменте

package example

import org.json4s.DefaultFormats
import org.json4s.native.JsonMethods.parse

class Foo {
  case class Person(name: String)
  def bar = {
    implicit val formats = DefaultFormats
    val expected = Person(name = "picard")
    val actual = parse("""{"name": "picard"}""").extract[Person]
    assert(expected == actual, s"$expected == $actual")
  }
}

object Main extends App {
  (new Foo).bar
}

терпит неудачу с

`java.lang.AssertionError: assertion failed: Person(picard) == Person(picard)`

, в то время как оно проходит, если мы перемещаем Person определение за пределы class Foo, как, например,

case class Person(name: String)
class Foo {
  def bar = {
    ...
    assert(expected == actual, s"$expected == $actual")
  }
}

Обратите внимание, что в обоих случаях десериализация кажется успешной, например,

assert(expected.name == actual.name)

выполняется независимо от case class Person местоположения определения.

Возможно, на нее как-то влияетнеявное Manifest передано extract?

Ответы [ 2 ]

4 голосов
/ 28 апреля 2019

Это ошибка.

https://github.com/json4s/json4s/issues/564 «Десериализованные внутренние классы case нельзя сравнивать с классами case, инициализированными в коде»

2 голосов
/ 28 апреля 2019

Похоже, что внутренние классы не могут быть осмысленно проверены на равенство, поскольку каждый экземпляр содержит ссылку на внешний объект. И эти ссылки являются частью проверки на равенство:

  class Outer {
    case class Inner(s: String)
  }

  val outer = new Outer()
  val a = outer.Inner("x")
  val b = outer.Inner("x")
  println(a==b) //true
  val c = new Outer().Inner("x")
  println(a==c) //false
...