Я пытаюсь сделать обобщенный сериалайзер для моих ADT типов данных, которые следуют следующему структурированному типуПроигрыша из-за erause, JSON сериализация с Jackson/Scalatra
/**
* Our standard ADT representation, indexed by ID. ADT's also have a formattedString (formal name representing ADT)
*/
type ADT = {def id: Long; def formattedName:String}
/**
* This is a structured type that forces the companion objects associated with an ADT to have an all value. This all
* value is an enumeration of all of the sum types of the ADT, and is generated by a macro
* @tparam A
*/
type ADTCompanion[A] = {val all:Set[A]}
Я также написал вспомогательные функции в работе с АТД, т.е.
/**
* Look up an sum type by its id
* @param companion The companion object being looked up
* @param id The id to look up
* @tparam A The type of the companion object
* @return The corresponding sum type
*/
def getADT[A <: ADT](companion:ADTCompanion[A], id:Long) = {
var re:Option[A] = None
try {
for (item <- companion.all) {
if (item.id == id) {
re = Some(item)
}
}
re.getOrElse(throw new InvalidId(companion,id))
} catch {
case e:Throwable => throw new InvalidId(companion,id)
}
}
/**
* Look up a sum type by its formattedName
* @param companion The companion object being looked up
* @param formattedName The formattedName to look up
* @tparam A The type of the companion object
* @return The corresponding sum type
*/
def getADT[A <: ADT](companion:ADTCompanion[A], formattedName:String) = {
var re:Option[A] = None
try {
for (item <- companion.all) {
if (item.formattedName == formattedName) {
re = Some(item)
}
}
re.getOrElse(throw new InvalidFormattedName(companion,formattedName))
} catch {
case e:Throwable => throw new InvalidFormattedName(companion,formattedName)
}
}
Теперь мой вопрос в следующем
private def jsonADTSerializer[A <: ADT](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (
{
case JObject
(JField
(`adtName`,
JObject(List(JField("id",JString(id)),JField("formattedName",formattedName)))) :: _) => getADT(adt,id.toLong)
},
{
case x: A => {
adtName -> (
("formattedName" -> x.formattedName) ~
("id" -> x.id)
)
}
}
)
sealed abstract class Test(val id: Long,val formattedName:String)
case object Test1 extends Test(1,"Test 1")
case object Test2 extends Test(2,"Test 2")
object Test {
val all:Set[Test] = SealedContents.values[Test]
}
sealed abstract class Foo(val id:Long, val formattedName:String)
case object Foo1 extends Foo(1,"Foo 1")
object Foo {
val all:Set[Foo] = SealedContents.values[Foo]
}
class TestSerializer extends CustomSerializer[Test](format => jsonADTSerializer("Test",Test))
class FooSerializer extends CustomSerializer[Foo](format => jsonADTSerializer("Foo",Foo))
Как вы можете видеть, что я пытаюсь уменьшить шаблонный с помощью функции jsonADTSerializer в сериализации моего АТДА, однако я получаю следующее сообщение об ошибке при компиляции приведенного выше кода
42: abstract type pattern A is unchecked since it is eliminated by erasure
[warn] case x: A => {
И неудивительно я получаю java.lang.NoSuchMethodException
сообщения об ошибках, когда используя код выше (так как А стерта, то case:x
набирает все, так что я получаю классы втягивается в jsonADTSerializer
, которые не соответствуют A
типа.)
Как вы убедитесь, что тип A
«s внутри jsonADTSerializer
не стирается, поэтому функция работает по назначению?
Кроме того, если вам интересно, я использую запечатанный содержимое макроса, который вы можете найти здесь https://stackoverflow.com/a/13672520/1519631
Информация о JSon сериализации scalatra можно найти здесь http://www.scalatra.org/guides/formats/json.html
UPDATE: Изменена typetage из jsonADTSerializer
- private def jsonADTSerializer[A <: ADT : ClassTag](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (
удаляет предупреждающее сообщение об стирании и устраняет проблему, спасибо!
Это удаляет предупреждающее сообщение, однако я теперь получаю эту проблему, где 'java.lang.NoSuchMethodException: com.example.Preference.formattedName() 'сообщение об ошибке времени выполнения, в этом случае оно вызвано' case x: A => {'собирание классов, которые фактически не соответствуют' A' (не имеют понятия, почему это происходит.) Информация о типе все еще теряется из-за стирания, 'A' во время выполнения должна содержать либо' Foo', либо 'Test', но вместо этого все подбирается – mdedetrich
Фактически nvm, it end заработал, забыл перезагрузить контейнер (doh!). Спасибо! – mdedetrich