2012-06-28 2 views
4

리버스 - json을 스칼라 벡터로 사용하여 json 배열을 비 직렬화 할 수 있습니까? 예를 들어리프트 -json을 사용하여 벡터를 비 직렬화

:

case class Foo(bar: Vector[Bar]) 

trait Bar { 
    def value: Int 
} 

case class Bar1(value: Int) extends Bar 

case class Bar2(value: Int) extends Bar  

import net.liftweb.json.{ShortTypeHints, Serialization, DefaultFormats} 

implicit val formats = new DefaultFormats { 
    override val typeHintFieldName = "type" 
    override val typeHints = ShortTypeHints(List(classOf[Foo],classOf[Bar1],classOf[Bar2])) 
} 

println(Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1))))) 

결과는 다음과 같습니다

{ 
    "type":"Foo", 
    "bar":[{ 
    "type":"Bar1", 
    "value":1 
    },{ 
    "type":"Bar2", 
    "value":5 
    },{ 
    "type":"Bar1", 
    "value":1 
    }] 
} 

좋음. ((BAR1을 구문 분석 JSON 값은 클래스 생성자의 인수 = 목록에 일치하지 않습니다 :

net.liftweb.json.MappingException :이 문자열

println(Serialization.read[Foo](Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1)))))) 

를 역 직렬화 할 때 나는 예외가 1), 바 2 (5), BAR1 (1)) arg를가 유형 = scala.collection.immutable. $ 콜론 $ 콜론 생성자는

그것은 test.Foo (scala.collection.immutable.Vector) 공공의 = 그 의미는 json arr ay는 클래스 Foo에 정의 된 벡터 유형이 아닌 스칼라 목록과 연관됩니다. net.liftweb.json.Serializer를 확장하여 사용자 지정 serializer를 만들고이를 형식 값에 포함시키는 방법이 있다는 것을 알고 있습니다. 그러나 Vector에 저장하는 객체 유형을 어떻게 복원 할 수 있습니까?

푸 (벡터 (BAR1 (1), 바 2 (5), BAR1 (1)))

답변

3

저는 종종 Lift의 List-centricness로 짜증을 났으며, 과거에 비슷한 일을해야한다고 생각했습니다. 다음은 제가 사용했던 방법입니다, 당신의 예를 들어 약간의 적응 : 추한의

trait Bar { def value: Int } 
case class Bar1(value: Int) extends Bar 
case class Bar2(value: Int) extends Bar 
case class Foo(bar: Vector[Bar]) 

import net.liftweb.json._ 

implicit val formats = new DefaultFormats { outer => 
    override val typeHintFieldName = "type" 
    override val typeHints = 
    ShortTypeHints(classOf[Bar1] :: classOf[Bar2] :: Nil) + 
    new ShortTypeHints(classOf[Foo] :: Nil) { 
     val FooName = this.hintFor(classOf[Foo]) 
     override def deserialize = { 
     case (FooName, foo) => foo \ "bar" match { 
      case JArray(bars) => Foo(
      bars.map(_.extract[Bar](outer, manifest[Bar]))(collection.breakOut) 
     ) 
      case _ => throw new RuntimeException("Not really a Foo.") 
     } 
     } 
    } 
} 

종류를, 아마 조금 정리 될 수 있지만 작동합니다.

+0

감사합니다. 내 예제에서 잘 작동합니다. 그러나 it'if 거기에 다른 형식으로 많은 벡터,이 모든 형식에 대한 deserialize 메서드를 재정의해야합니까? 그리고이 예제는 어떻습니까? 'case 클래스 Bar3 (값 : Int, bars2 : 벡터 [Bars2])은 Bar를 확장합니다. 다른 보편적 인 솔루션이 있습니까? –

1

당신은 암시 적 변환을 추가 할 수 있습니다 :이 같은 직렬화 복원의 결과를 얻을 싶어

implicit def listToVect(list:List[Bar]):Vector[Bar] = list.map(identity)(breakOut) 

그 후 은 예상대로 작동합니다.

+0

작동하지 않습니다. 이 암시 적 변환은이 계층이 아니라 메소드 읽기 실행의 깊이에 있어야한다고 생각합니다. 아니면이 코드를 삽입하라는 뜻입니까? –

+0

REPL에서 사용해 보았습니다. implicits는 작동 범위에 있어야합니다. 예 : 필요한 수업에서 가져와야합니다. –