lucidsoftware/xtract

Parsing case classes with more than 22 fields

Closed this issue · 3 comments

Hello,

I've been successfully using the library to parse a complex XML file, but ran into an instance where my case class has more than 22 fields. Assuming it was all just strings, you would do something like this according to examples:

object Foo {
  implicit val reader: XmlReader[Foo] = (
    attribute[String]("A"),
    attribute[String]("B"),
    attribute[String]("C"),
    attribute[String]("D"),
    attribute[String]("E"),
    attribute[String]("F"),
    attribute[String]("G"),
...
    attribute[String]("Z"),
  ) mapN(apply _)
}

This won't work due to Scala's limit on 22 tuples. Is there anyway to parse the case class in Xtract without simply breaking down the class? I see that in play-json, this case can be solved with two separate readers. Is something like that possible with Xtract?

I see that in play-json, this case can be solved with two separate readers. Is something like that possible with Xtract?

Probably, do you have a link or code snippet to how that is done with play-json?

Sure, not a problem. Here's a link I found describing the issue:

https://stackoverflow.com/questions/28167971/scala-case-having-22-fields-but-having-issue-with-play-json-in-scala-2-11-5

import play.api.libs.json._
import play.api.libs.functional.syntax._

// Let's pretend this is huge:
case class Huge(a: Int, b: String, c: Boolean, d: List[Int])

val fields1to2: Reads[(Int, String)] = (
  (__ \ "a").read[Int] and
  (__ \ "b").read[String]
).tupled

val fields3to4: Reads[(Boolean, List[Int])] = (
  (__ \ "c").read[Boolean] and
  (__ \ "d").read[List[Int]]
).tupled

implicit val hugeCaseClassReads: Reads[Huge] = (
  fields1to2 and fields3to4
) {
  case ((a, b), (c, d)) =>  
    Huge(a, b, c, d)
}

Another code snippet I found handling it in a similar way: https://gist.github.com/EdgeCaseBerg/e2b366644802eec1263ddbf130f9df4f

Sorry, it took so long to respond. I think you should be able to do something pretty similar with xtract. Something like:

import com.lucidchart.open.xtract._
import cats.syntax.all._

case class Huge(a: Int, b: String, c: Boolean, d: List[Int])

val fields1to2: XmlReader[(Int, String)] = (
  (__ \ "a").read[Int],
  (__ \ "b").read[String]
).tupled

val fields3to4: XmlReader[(Boolean, List[Int])] = (
  (__ \ "c").read[Boolean],
  (__ \ "d").read[List[Int]]
).tupled

implicit val hugeCaseClassReads: XmlReader[Huge] = (
  fields1to2, fields3to4
).mapN { case ((a, b), (c, d)) =>  
    Huge(a, b, c, d)
}