Search code examples
jsonscalaplayframeworkcase-class

Using Play Framework and case class with greater than 22 parameters


I have seen some of the other issues involving the infamous "22 fields/parameters" issue that is an inherent bug (feature?) of Scala V < 2.11. See here and here. However, as per this blog post, it appears that the 22 parameter limit in case class has been fixed; at least where the language is concerned.

I have a case class that I want to load an arbitrary (Read: > 22) number of values into which will later be read into a JSON object using the Play library.

It looks something like this:

object L {
  import play.api.libs.json.Reads. _
  import play.api.libs.functional.syntax._

  implicit val responseRead: Reads[L] = (
    MyField1.jsPath.Read[MyField1.t] and 
    MyField2.jsPath.Read[MyField2.t] and
    ...
    MyField35.jsPath.Read[MyField35.t]
  ) (L.apply _)
}

case class L(myField1: MyField1.t, myField2: MyField2.t, ... myField35: MyField35.t)

The issue is that on compile, Scala complains that there are more than 22 parameters in the case class. (Specifically: on the last line of the object definition, when the compiler attempts to build, I get: "implementation restricts functions to 22 parameters".) I'm currently using Scala v2.11.6, so I think it's not a language issue. That makes me think that the Play library hasn't updated their implementation of Read.

If that's the case, then I guess the best bet is to group related fields into Tuples and pass the Tuples in through the JSON API?


Solution

  • So the answer to this question is actually two parts:

    1. Workaround

    I'll call this the "workaround" because while it does "work" it usually addresses the symptom and not the problem.

    My solution was to use shapeless to provide generic heterogeneous lists of arbitrary length. This solution is already widely discussed and available elsewhere. See, e.g., (1) [SO Post] How to get around the Scala case class limit of 22 fields?; (2) Blog post; (3) Yet another blog post.

    2. Solution

    As @jeffrey-chung mentions is to restructure the model to deal with this limit. As many in the industry have noted, having a function with more than 30 arguments is likely a sign that your function is doing too much or that the function should be refactored to ingest a smaller number of arguments. See, e.g., (1) Rule of 30 – When is a method, class or subsystem too big?; (2) Databrick's style guide.