2012-10-09 13 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]にする方法はありますか?私はこの1つの方法を使用することを避けたい:

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 
} 

Scalaでそうする方法がない場合は、クラスのプロパティを反復処理する方法はありますか?たぶん私はそれを行うための汎用関数を作成することができます:

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

はいそれが可能です。 Scala 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で信じられないほど繰り返されています。タイプセーフな実装が必要な場合は、この問題は自明ではありません。

この問題を解決する1つの方法は、リフレクション(示唆したとおり)を使用することですが、私は個人的にはタイプシステムと暗黙的な方法を使用することを好みます。

非常にスマートな人間によって開発された、よく知られているライブラリがあります。このライブラリでは、あらゆるケースクラスをタイプセーフな異種リストに変換するなどの高度な操作を実行できます。また、記録"。ライブラリは型崩れと呼ばれ、ここでは一例であり:

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?

関連する問題