scala - collection - automapper nested mapping
¿Hay algo como AutoMapper para Scala? (3)
He estado buscando alguna API fluida para el mapeo objeto objeto, similar a AutoMapper . ¿Hay tales herramientas en Scala?
Creo que hay menos necesidad de algo como AutoMapper en Scala, porque si utiliza los modelos idiomáticos de Scala es más fácil escribir y manipular y porque puede definir fácilmente el aplanamiento / proyección automático mediante conversiones implícitas.
Por ejemplo, aquí es el equivalente en Scala del ejemplo de aplanamiento de AutoMapper:
// The full model
case class Order( customer: Customer, items: List[OrderLineItem]=List()) {
def addItem( product: Product, quantity: Int ) =
copy( items = OrderLineItem(product,quantity)::items )
def total = items.foldLeft(0.0){ _ + _.total }
}
case class Product( name: String, price: Double )
case class OrderLineItem( product: Product, quantity: Int ) {
def total = quantity * product.price
}
case class Customer( name: String )
case class OrderDto( customerName: String, total: Double )
// The flattening conversion
object Mappings {
implicit def order2OrderDto( order: Order ) =
OrderDto( order.customer.name, order.total )
}
//A working example
import Mappings._
val customer = Customer( "George Costanza" )
val bosco = Product( "Bosco", 4.99 )
val order = Order( customer ).addItem( bosco, 15 )
val dto: OrderDto = order // automatic conversion at compile-time !
println( dto ) // prints: OrderDto(George Costanza,74.85000000000001)
PD: No debería usar Doble para cantidades de dinero ...
Estoy de acuerdo con @paradigmatic, es cierto que el código será mucho más limpio al usar Scala, pero a veces puedes encontrarte con mapeos entre clases de casos que parecen muy similares, y eso es solo una pérdida de pulsaciones de teclas.
Empecé a trabajar en un proyecto para abordar los problemas, puede encontrarlo aquí: https://github.com/bfil/scala-automapper
Utiliza macros para generar los mapeos por ti.
En el momento en que puede asignar una clase de caso a un subconjunto de la clase de caso original, maneja opciones y campos opcionales, así como otras cosas menores.
Todavía estoy intentando averiguar cómo diseñar la api para que sea compatible con el cambio de nombre o la asignación de campos específicos con lógica personalizada, cualquier idea o entrada sería muy útil.
Se puede usar para algunos casos simples en este momento y, por supuesto, si la asignación se vuelve muy compleja, podría ser mejor definir la asignación manualmente.
La biblioteca también permite definir manualmente los tipos de Mapping
entre clases de casos en cualquier caso que pueden proporcionarse como un parámetro implícito a un AutoMapping.map(sourceClass)
o sourceClass.mapTo[TargetClass]
.
ACTUALIZAR
Acabo de lanzar una nueva versión que maneja Iterables, Maps y permite pasar asignaciones dinámicas (para admitir el cambio de nombre y la lógica personalizada, por ejemplo)
Para mapeos complejos uno puede querer considerar mapeadores basados en Java como
- http://modelmapper.org/user-manual/property-mapping/#conditional-mapping
- http://github.com/smooks/smooks/tree/v1.5.1/smooks-examples/model-driven-basic-virtual/
- http://orika-mapper.github.io/orika-docs/advanced-mappings.html
Se puede acceder a los objetos Scala desde Java:
- http://lampwww.epfl.ch/~michelou/scala/using-scala-from-java.html
- http://lampwww.epfl.ch/~michelou/android/java-to-scala.html
Las implementaciones de conversiones implícitas para objetos complejos serían más suaves con los mapeos declarativos que los hechos a mano.
Encontró una lista más larga aquí:
http://www.javacodegeeks.com/2013/10/java-object-to-object-mapper.html