2012-10-09 3 views
11

의 내가이 클래스스칼라에서 객체의 값을 Map [String, String]으로 변환하는 방법은 무엇입니까?

case class Test (id: Long, name: String) 

이 클래스의 인스턴스가 있다고 가정 해 봅시다 :

Test : 
id -> 1 
name -> toto 
나는 다음과 같은지도 [문자열, 문자열] 만들려는

:

Map("id" -> "1", "name" -> "toto") 

제 질문은이 Test 인스턴스를 Map [String, String]으로 변환 할 수 있습니까? 나는이 일 등의 방법을 사용하지 않도록하려면 : 스칼라에서 그렇게 할 수있는 방법이없는

def createMap(instance: Test): Map[String, String] = { 
    val map = new Map[String, String] 
    map.put("id", instance.id.toString) 
    map.put("name", instance.name) 
    map 
} 

경우, 클래스의 속성을 반복하는 방법은 무엇입니까? 어쩌면 내가 할 수있는 일반적인 함수를 만들 수 있습니다 :

def createMap(instance: T): Map[String, String] = { 
    val map = new Map[String, String] 
    //pseudocode 
    for ((name, value) <- instance.getClassProperties.getValues) { 
     case value.isInstanceOf[String] : map.push(name, value) 
     case _ : map.push(name, value.toString) 
    } 
    map 
} 

그것은 가능합니까? 좋은 예제/링크가 있으면 관심이 있습니다.

+0

[이 질문에 대한 답변] (http://stackoverflow.com/questions/2224251/reflection-on-a-scalacase-class)이 도움이 될 수 있습니다. – incrop

+0

일반 솔루션이 마음에 들지는 않지만이 문제는'Map ("id"-> t.id.toString, "name"-> t.name)''t '가 '시험 '. – sschaef

+0

팁 주셔서 감사합니다! – alexgindre

답변

19

예 가능 : 당신이 더 많은 것을 알고에 관심이 있다면, 좋은 시작점이 게시물 수 있습니다. 스칼라 2.10부터 리플렉션을 사용할 수 있습니다. 당신을 가정

가 있습니다

val test = Test(23423, "sdlkfjlsdk") 

다음은 당신이 원하는 무엇을 얻을 것이다 :

import reflect.runtime.universe._ 
import reflect.runtime.currentMirror 

val r = currentMirror.reflect(test) 
r.symbol.typeSignature.members.toStream 
    .collect{case s : TermSymbol if !s.isMethod => r.reflectField(s)} 
    .map(r => r.symbol.name.toString.trim -> r.get.toString) 
    .toMap 

는 단순히 인스턴스의 경우 클래스 사용 .productIterator의 필드 값을 반복하십시오.

+0

이 과정을 되돌릴 수 있습니까 ?? 지도에서 객체로? 수업 전체 이름이 주어진 경우 –

+1

@ JeffLee 예. 리플렉션과 매크로 모두 가능합니다. 여기 [Scala 2.10의 리플렉션을 사용한 예제] (https://github.com/sorm/sorm/blob/master/src/main/scala/sorm/reflection/Reflection.scala#L50-L58). –

10

처리중인 주제가 StackOverFlow에서 엄청나게 반복적으로 발생하고 유형 안전 구현을 원할 경우 문제가 드뭅니다.

이 문제를 해결하는 한 가지 방법은 리플렉션 (권장)을 사용하는 것이지만 개인적으로 유형 시스템과 암시를 사용하는 것이 더 좋습니다.

매우 똑똑한 사람이 개발 한 잘 알려진 라이브러리가 있습니다.이 라이브러리는 모든 사례 클래스를 형식이 안전한 이기종 목록으로 바꾸거나 고급 매핑을 만들 수있는 고급 작업을 수행하거나 "확장 가능 기록 ". 라이브러리는 하나의 예 여기 무형라고하고있다 :

object RecordExamples extends App { 
    import shapeless._ 
    import HList._ 
    import Record._ 

    object author extends Field[String] { override def toString = "Author" } 
    object title extends Field[String] { override def toString = "Title" } 
    object id  extends Field[Int]  { override def toString = "ID" } 
    object price extends Field[Double] { override def toString = "Price" } 
    object inPrint extends Field[Boolean] { override def toString = "In print" } 

    def printBook[B <: HList](b : B)(implicit tl : ToList[B, (Field[_], Any)]) = { 
    b.toList foreach { case (field, value) => println(field+": "+value) } 
    println 
    } 

    val book = 
    (author -> "Benjamin Pierce") :: 
    (title -> "Types and Programming Languages") :: 
    (id  -> 262162091) :: 
    (price -> 44.11) :: 
    HNil 

    printBook(book) 

    // Read price field 
    val currentPrice = book.get(price) // Static type is Double 
    println("Current price is "+currentPrice) 
    println 

    // Update price field, relying on static type of currentPrice 
    val updated = book + (price -> (currentPrice+2.0)) 
    printBook(updated) 

    // Add a new field 
    val extended = updated + (inPrint -> true) 
    printBook(extended) 

    // Remove a field 
    val noId = extended - id 
    printBook(noId) 
} 

도서 키로 개체를 사용하여 색인 할 수있는 형태 보증 된지도처럼 동작합니다.

Are HLists nothing more than a convoluted way of writing tuples?

관련 문제