Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Support for flattening models #100

Closed
holinov opened this issue Mar 11, 2019 · 4 comments
Closed

[Feature request] Support for flattening models #100

holinov opened this issue Mar 11, 2019 · 4 comments

Comments

@holinov
Copy link

holinov commented Mar 11, 2019

It would be great to have possibility to map inner fields of object to top level object.

// Source classes
case class InnerData(name: String, ival: Int)
case class DataHolder(v: Int, data: InnerData)
case class OtherDataHolder(v: Int, data: InnerData)

// Target class
case class Target(v: Int, name: String, ival: Int)

It would be nice to have any way to tell transformer that i need to extract fields from inner classes
Now i'm using workaround like this

object InnerData {
  implicit val intoNameString: Transformer[InnerData, String] = _.name
  implicit val intoIntVal: Transformer[InnerData, Int] = _.ival
}

val data = DataHolder(1, InnerData("name_val", 10))
data
      .into[Target]
      .withFieldRenamed(_.data, _.name)
      .withFieldRenamed(_.data, _.ival)
      .transform

Main problem here is that i have no possibility to reuse it on OtherDataHolder so i need every time to write this code.

@REDNBLACK
Copy link

Yeah, would be even better if it supported shapeless.Witness selector for fieldFrom/fieldTo names, like this:

LabelledTransformer[FieldFrom <: Symbol, FieldTo <: Symbol, From, To]

object InnerData {
  implicit val intoNameString: LabelledTransformer[W.`'data`.T, W.`'name`.T, InnerData, String] = _.name
  implicit val intoIntVal: LabelledTransformer[W.`'data`.T, W.`'ival`.T, InnerData, Int] = _.ival
}

@krzemin
Copy link
Member

krzemin commented Apr 7, 2019

One of possible solutions to this problem would be to allow pulling fields from nested case classes and pushing them down to nested.

DataHolder(1, InnerData("name_val", 10))
  .into[Target]
  .withFieldsPulledFrom(_.data)
  .transform
 
Target(1, "name_val", 10)
  .into[DataHolder]
  .withFieldsPushedTo(_.data, _.name, _.ival)
  .transform

It could work as long as pulling/pushing fields doesn't introduce name clash.

Other possibility is to generalize renaming to support renaming of nested fields as well:

DataHolder(1, InnerData("name_val", 10))
  .into[Target]
  .withFieldRenamed(_.data.name, _.name)
  .withFieldRenamed(_.data.ival, _.ival)
  .transform

Target(1, "name_val", 10)
  .into[DataHolder]
  .withFieldRenamed(_.name, _.data.name)
  .withFieldRenamed(_.ival, _.data.ival)
  .transform

Actually, both proposals are orthogonal and can be implemented independently.

@holinov
Copy link
Author

holinov commented Jun 25, 2019

as for my purposes 2nd way is ok

@holinov
Copy link
Author

holinov commented Sep 17, 2019

great thx

@holinov holinov closed this as completed Sep 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants