2013-10-25 3 views
0

Я пытаюсь сделать обобщенный сериалайзер для моих 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]) = ( удаляет предупреждающее сообщение об стирании и устраняет проблему, спасибо!

ответ

1

Я думаю, вам просто нужно будет добавить в ClassTag контексте Bound для вас определение метода:

import scala.reflect._ 
private def jsonADTSerializer[A <: ADT : ClassTag](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (

...rest as before... 
+0

Это удаляет предупреждающее сообщение, однако я теперь получаю эту проблему, где 'java.lang.NoSuchMethodException: com.example.Preference.formattedName() 'сообщение об ошибке времени выполнения, в этом случае оно вызвано' case x: A => {'собирание классов, которые фактически не соответствуют' A' (не имеют понятия, почему это происходит.) Информация о типе все еще теряется из-за стирания, 'A' во время выполнения должна содержать либо' Foo', либо 'Test', но вместо этого все подбирается – mdedetrich

+0

Фактически nvm, it end заработал, забыл перезагрузить контейнер (doh!). Спасибо! – mdedetrich

Смежные вопросы