Is there something like AutoMapper for Scala?
Asked Answered
M

3

20

I have been looking for some scala fluent API for mapping object-object, similar to AutoMapper. Are there such tools in Scala?

Manganin answered 30/7, 2011 at 19:36 Comment(5)
While looking up AutoMapper I ran into this SO post: Automapper for Java? which mentions a few possibilities, including Dozer. Not necessarily "Scala", but...Overlord
By this time, someone must have already started developping one in Scala...Manganin
Nothing exists for Scala that I know of. I do plan to write a property mapping API for ModelMapper that better leverages some of Scala's features, but for now you can certainly use ModelMapper as it is for Java.Quotha
I'm actually thinking about writing one, just as a more or less useful practice for macros :-)Amberly
I developed one some time ago which derives a mapping in compile time: scalalandio.github.io/chimneySchoolroom
O
13

I think there's less need of something like AutoMapper in Scala, because if you use idiomatic Scala models are easier to write and manipulate and because you can define easily automatic flattening/projection using implicit conversions.

For example here is the equivalent in Scala of AutoMapper flattening example:

// 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)

PS: I should not use Double for money amounts...

Owner answered 5/8, 2011 at 8:38 Comment(0)
T
6

I agree with @paradigmatic, it's true that the code will be much cleaner using Scala, but sometimes you can find yourself mapping between case classes that look very similar, and that's just a waste of keystrokes.

I've started working on a project to address the issues, you can find it here: https://github.com/bfil/scala-automapper

It uses macros to generate the mappings for you.

At the moment it can map a case class to a subset of the original case class, it handles optionals, and optional fields as well as other minor things.

I'm still trying to figure out how to design the api to support renaming or mapping specific fields with custom logic, any idea or input on that would be very helpful.

It can be used for some simple cases right now, and of course if the mapping gets very complex it might just be better defining the mapping manually.

The library also allows to manually define Mapping types between case classes in any case that can be provided as an implicit parameter to a AutoMapping.map(sourceClass) or sourceClass.mapTo[TargetClass] method.

UPDATE

I've just released a new version that handles Iterables, Maps and allows to pass in dynamic mappings (to support renaming and custom logic for example)

Terri answered 17/9, 2015 at 9:6 Comment(0)
S
2

For complex mappings one may want to consider Java based mappers like

Scala objects can be accessed from Java:

Implementations of implicit conversions for complex objects would be smoother with declarative mappings than handcrafted ones.

Found a longer list here:

http://www.javacodegeeks.com/2013/10/java-object-to-object-mapper.html

Starnes answered 27/12, 2014 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.