Scala case having 22 fields but having issue with play-json in scala 2.11.5

前端 未结 2 1589
Happy的楠姐
Happy的楠姐 2020-12-05 04:31

With Scala 2.11, we are allowed to have more then 22 fields in a case class right??

case class SomeResponse(
                                     var composi         


        
相关标签:
2条回答
  • 2020-12-05 05:13

    To make the example above compile, I had to make the type explicit:

    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])
    
    object Huge {
      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
    
      val f: ((Int, String), (Boolean, List[Int])) => Huge = {
        case ((a, b), (c, d)) => Huge(a, b, c, d)
      }
    
      implicit val hugeCaseClassReads: Reads[Huge] = (
        fields1to2 and fields3to4
      ) { f }
    
    }
    
    0 讨论(0)
  • 2020-12-05 05:20

    You can split your Reads definition:

    val fields1to10: Reads[(A,B,C,D,E,F,G,H,I,J)] = ???
    val fields11to20 = ???
    val fields21to30 = ???
    
    implicit val hugeCaseClassReads: Reads[HugeCaseClass] = (
      fields1to10 and fields11to20 and fields21to30
    ) { a, b, c => createHugeCaseClassFromThreeTuples(a, b, c) }
    

    The reason why "functional syntax" doesn't work for more than 22 fields is because there are intermediate classes defined only up to 22: FunctionalBuilder


    Fully written out for small example it would look like:

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

    And the result of tryint to validate null:

    scala> JsNull.validate[Huge]
    res6: play.api.libs.json.JsResult[Huge] = JsError(
      List(
        (/b,List(ValidationError(error.path.missing,WrappedArray()))),
        (/d,List(ValidationError(error.path.missing,WrappedArray()))),
        (/c,List(ValidationError(error.path.missing,WrappedArray()))),
        (/a,List(ValidationError(error.path.missing,WrappedArray())))))
    

    As you can see, all fields are tried.


    Or you could extend play with even more CanBuildNN classes: https://github.com/playframework/playframework/blob/2.3.6/framework/src/play-functional/src/main/scala/play/api/libs/functional/Products.scala


    Yet I'd advice you to group fields in the SomeResponse class, for example address related etc. And write Reads and Writes instances by hand, if the JSON structure is flat and cannot be changed.

    0 讨论(0)
提交回复
热议问题