[SCALA] 스칼라 : 케이스 클래스로 변환지도
SCALA스칼라 : 케이스 클래스로 변환지도
하자 내가이 예제의 경우 클래스가 있다고 가정 해
case class Test(key1: Int, key2: String, key3: String)
그리고지도를 가지고
myMap = Map("k1" -> 1, "k2" -> "val2", "k3" -> "val3")
이 같은 코드, 뭔가의 여러 장소에서 내 경우 클래스에이지도를 변환해야합니다 :
myMap.asInstanceOf[Test]
그 일을 가장 쉬운 방법이 있을까요? 어떻게 든 이것에 대한 암시를 사용할 수 있습니까?
해결법
-
==============================
1.우아하게이 일을 두 가지 방법. 먼저 당신을 위해 변환을 할 수있는 타입의 클래스를 암시 클래스 (2.10+)를 사용하기 위해 적용 취소, 두 번째를 사용하는 것입니다.
우아하게이 일을 두 가지 방법. 먼저 당신을 위해 변환을 할 수있는 타입의 클래스를 암시 클래스 (2.10+)를 사용하기 위해 적용 취소, 두 번째를 사용하는 것입니다.
1)는 적용 취소 이러한 변환을 작성하는 가장 간단하고 똑 바른 앞으로 방법입니다. 그것은 어떤 "마술"을하지 않습니다와 IDE를 사용하는 경우 쉽게 찾을 수 있습니다. 컴패니언 객체를 어수선하게하고 싶지 않을 수도 있습니다 장소에서 새싹 종속성에 코드를 일으킬 수 있습니다 이런 종류의 일을, 메모를 수행합니다
object MyClass{ def unapply(values: Map[String,String]) = try{ Some(MyClass(values("key").toInteger, values("next").toFloat)) } catch{ case NonFatal(ex) => None } }
어떤이처럼 사용할 수 있습니다 :
val MyClass(myInstance) = myMap
완전히 일치하지 않는 경우에 예외를 슬로우로,주의하십시오.
타입 클래스를 사용하면 더 많은 보일러를 만들지 만 다른 경우 클래스에 적용하는 동일한 패턴을 확장 객실의 많은 수와 2) 암시 적 클래스를 수행 :
implicit class Map2Class(values: Map[String,String]){ def convert[A](implicit mapper: MapConvert[A]) = mapper conv (values) } trait MapConvert[A]{ def conv(values: Map[String,String]): A }
그리고 예를 들어 당신은 같은 것을 할 것입니다 :
object MyObject{ implicit val new MapConvert[MyObject]{ def conv(values: Map[String, String]) = MyObject(values("key").toInt, values("foo").toFloat) } }
당신이 위에서 설명했던대로 후 바로 사용할 수있는 :
val myInstance = myMap.convert[MyObject]
어떤 변환이 이루어지지 할 수있는 경우 예외를 throw. 어떤 개체에 맵 [문자열, 문자열] 간의 변환이 패턴을 사용하여 또 다른 암시적인 (그리고 암시 적 범위로한다.) 필요
-
==============================
2.여기서 스칼라 리플렉션을 사용하는 다른 비 상용구 방법 (상기 스칼라 2.10)이며, 별도로 컴파일 된 모듈을 필요로하지 않는다 :
여기서 스칼라 리플렉션을 사용하는 다른 비 상용구 방법 (상기 스칼라 2.10)이며, 별도로 컴파일 된 모듈을 필요로하지 않는다 :
import org.specs2.mutable.Specification import scala.reflect._ import scala.reflect.runtime.universe._ case class Test(t: String, ot: Option[String]) package object ccFromMap { def fromMap[T: TypeTag: ClassTag](m: Map[String,_]) = { val rm = runtimeMirror(classTag[T].runtimeClass.getClassLoader) val classTest = typeOf[T].typeSymbol.asClass val classMirror = rm.reflectClass(classTest) val constructor = typeOf[T].decl(termNames.CONSTRUCTOR).asMethod val constructorMirror = classMirror.reflectConstructor(constructor) val constructorArgs = constructor.paramLists.flatten.map( (param: Symbol) => { val paramName = param.name.toString if(param.typeSignature <:< typeOf[Option[Any]]) m.get(paramName) else m.get(paramName).getOrElse(throw new IllegalArgumentException("Map is missing required parameter named " + paramName)) }) constructorMirror(constructorArgs:_*).asInstanceOf[T] } } class CaseClassFromMapSpec extends Specification { "case class" should { "be constructable from a Map" in { import ccFromMap._ fromMap[Test](Map("t" -> "test", "ot" -> "test2")) === Test("test", Some("test2")) fromMap[Test](Map("t" -> "test")) === Test("test", None) } } }
-
==============================
3.조나단 차우는 구현이 동작을 일반화하고 보일러를 제거 (스칼라 2.11을 위해 설계) 스칼라 매크로를.
조나단 차우는 구현이 동작을 일반화하고 보일러를 제거 (스칼라 2.11을 위해 설계) 스칼라 매크로를.
http://blog.echo.sh/post/65955606729/exploring-scala-macros-map-to-case-class-conversion
import scala.reflect.macros.Context trait Mappable[T] { def toMap(t: T): Map[String, Any] def fromMap(map: Map[String, Any]): T } object Mappable { implicit def materializeMappable[T]: Mappable[T] = macro materializeMappableImpl[T] def materializeMappableImpl[T: c.WeakTypeTag](c: Context): c.Expr[Mappable[T]] = { import c.universe._ val tpe = weakTypeOf[T] val companion = tpe.typeSymbol.companionSymbol val fields = tpe.declarations.collectFirst { case m: MethodSymbol if m.isPrimaryConstructor ⇒ m }.get.paramss.head val (toMapParams, fromMapParams) = fields.map { field ⇒ val name = field.name val decoded = name.decoded val returnType = tpe.declaration(name).typeSignature (q"$decoded → t.$name", q"map($decoded).asInstanceOf[$returnType]") }.unzip c.Expr[Mappable[T]] { q""" new Mappable[$tpe] { def toMap(t: $tpe): Map[String, Any] = Map(..$toMapParams) def fromMap(map: Map[String, Any]): $tpe = $companion(..$fromMapParams) } """ } } }
-
==============================
4.이 코드를 사랑하지 않아,하지만 난 당신이 튜플로지도 값을 가져 다음의 경우 클래스의 tupled 생성자를 사용할 수있는 경우이 가능 같아요. 즉 다음과 같이 보일 것입니다 :
이 코드를 사랑하지 않아,하지만 난 당신이 튜플로지도 값을 가져 다음의 경우 클래스의 tupled 생성자를 사용할 수있는 경우이 가능 같아요. 즉 다음과 같이 보일 것입니다 :
val myMap = Map("k1" -> 1, "k2" -> "val2", "k3" -> "val3") val params = Some(myMap.map(_._2).toList).flatMap{ case List(a:Int,b:String,c:String) => Some((a,b,c)) case other => None } val myCaseClass = params.map(Test.tupled(_)) println(myCaseClass)
당신은 확실히 값 목록 정확히 3 개 요소이며, 그들이 올바른 종류가 있는지 확인하기 위해주의해야합니다. 그렇지 않다면, 당신은 대신 없음으로 끝낼. 나는이 위대한하지 말했지만, 그것이 가능하다는 것을 보여주고있다.
-
==============================
5.당신이 스칼라에 대해 잭슨을 사용하는 경우에, 나를 위해 잘 작동합니다 :
당신이 스칼라에 대해 잭슨을 사용하는 경우에, 나를 위해 잘 작동합니다 :
def from[T](map: Map[String, Any])(implicit m: Manifest[T]): T = { val mapper = new ObjectMapper() with ScalaObjectMapper mapper.convertValue(map) }
POJO에지도 <문자열, 문자열> 변환 :에서 참조
-
==============================
6.
commons.mapper.Mappers.mapToBean[CaseClassBean](map)
세부 : https://github.com/hank-whu/common4s
from https://stackoverflow.com/questions/20684572/scala-convert-map-to-case-class by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라 : VAR-인수 기능에 패스 서열 (0) | 2019.11.15 |
---|---|
[SCALA] 어떻게 문맥에 관련한 타입 클래스의 인스턴스 바인딩을받을 수 있나요? (0) | 2019.11.15 |
[SCALA] 어떻게 다른 SBT 프로젝트에서 외부 SBT 프로젝트를 참조하는? (0) | 2019.11.15 |
[SCALA] Groovy의 안전 참조 연산자 최고의 스칼라 모방 (?).? (0) | 2019.11.15 |
[SCALA] 스칼라의 forSome 키워드는 무엇입니까? (0) | 2019.11.15 |