Параметр типа Scala, похоже, " застрял"
Я использую лифт-JSON, чтобы де-сериализации в JSON строки в case-классы в Scala. JSON, который я анализирую, имеет общую структуру: поле данных, успеха и ошибки, где данные содержат интересные биты. Я создал класс APIResponse для учета этой структуры и простой метод синтаксического анализа, который принимает параметр типа для типа объекта, содержащегося в "data":
import net.liftweb.json.Serialization.read
import net.liftweb.json.DefaultFormats
object JSONParseTest extends App {
implicit val formats = DefaultFormats
def parse[T: Manifest](json: String) = {
read[APIResponse[T]](json)
}
val resultA = parse[TypeA](""" { "data": { "foo": "string" }, "success": true } """)
println(resultA)
val resultB = parse[TypeB](""" { "data": { "bar": "string" }, "success": true } """)
println(resultB)
}
case class TypeA(foo: String)
case class TypeB(bar: String)
case class APIResponse[D](data: D, success: Boolean, error: Option[String]) {
override def toString: String =
if(success) {
"SUCCESSFUL: " + data.toString
} else {
"ERROR: " + error.get
}
}
Все работает отлично...для первого разобранного объекта. По какой-то причине, однако, второй объект разобран кажется, что он "застрял", выполняя, как если бы был передан первый параметр типа вместо второго. Как вы можете видеть в выходных данных ниже, lift-json ищет поле 'foo' в строке JSON и не может его найти; 'foo' существует на TypeA, но не на TypeB. Я проверил манифест в методе синтаксического анализа, и там есть правильный тип. Если я комментирую первый синтаксический анализ / печать, второй начинает работать. Какие-нибудь указания на то, почему это не ведет себя так, как ожидалось? Это как бы ошеломляет меня. ум.
SUCCESSFUL: TypeA(string)
Exception in thread "main" net.liftweb.json.MappingException: No usable value for data
No usable value for foo
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$12.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$12.apply(Extraction.scala:253)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:233)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:233)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:76)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:233)
at scala.collection.immutable.List.map(List.scala:76)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:366)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:199)
at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:300)
at net.liftweb.json.Serialization$.read(Serialization.scala:58)
at jmullin.api.Test$.parse(API.scala:11)
at jmullin.api.Test$delayedInit$body.apply(API.scala:16)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:76)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:30)
at scala.App$class.main(App.scala:60)
at jmullin.api.Test$.main(API.scala:7)
at jmullin.api.Test.main(API.scala)
Caused by: net.liftweb.json.MappingException: No usable value for foo
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$12.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$12.apply(Extraction.scala:253)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:233)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:233)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:76)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:233)
at scala.collection.immutable.List.map(List.scala:76)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 29 more
Caused by: net.liftweb.json.MappingException: Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.convert(Extraction.scala:403)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:314)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 42 more
1 ответ:
Получается лифт-JSON это делают некоторые мемоизация класса в конструктор сопоставления кулуарно, игнорируя аргументы типа. Когда поиск выполняется для одного и того же класса с различными параметрами типа, возвращается старый конструктор, что приводит к путанице, наблюдаемой здесь. Тайна решена (хотя проблема не решена).