Java
Scala

Scalaのcase classを見やすく整形する

More than 1 year has passed since last update.

コメントでcase classを見やすく整形するPPrintというライブラリーがある事を教えていただきました。
http://www.lihaoyi.com/PPrint/

以下commons-lang3を使った方法ですが、上記のライブラリが使いやすいので、特別な事情がなければPPrintをつかうとよいと思います。


Scalaのcase classの中身を整形して表示させたかったのですが、
"case class pretty print" とか "scala 整形 出力" 等でやり方を検索してもヒットしなかったため整形方法を共有します。

整形方法

Scalaのcase classはJavaのBean相当のclassにコンパイルされるため
Javaのcommons-lang3に含まれるToStringBuilderを使用して整形します。

commons-lang3:
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3

表示するオブジェクト

以下のcase classの値を整形して表示します。

code
case class Outer(title: String, note: Seq[Inner])
case class Inner(no: Int, memo: String)

val obj = Outer("タイトル", Inner(1, "いろは") :: Inner(2, "にほへと")  :: Inner(3, "ちりぬるを") :: Nil)
println(obj)
console
Outer(タイトル,List(Inner(1,いろは), Inner(2,にほへと), Inner(3,ちりぬるを)))

階層化されたクラスの1階層目までを整形して表示する

ToStringBuilderのreflectionToStringを使用する事でbean形式のオブジェクトの値を整形する事ができます。

code
val text1 = ToStringBuilder.reflectionToString(obj, ToStringStyle.MULTI_LINE_STYLE)
println(text1)
console
Outer@1df5f8ae[
  title=タイトル
  note=List(Inner(1,いろは), Inner(2,にほへと), Inner(3,ちりぬるを))
]

ToStringStyleに上記の形式だけでなく、値だけ表示するものやJSON形式に整形するものなどもあります。

ToStringStyle:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ToStringStyle.html

階層化されたcase classも再帰的に整形して表示する

MultilineRecursiveToStringStyleを使用する事でcase class型になっているフィールドの中身まで再帰的に整形する事ができます。

code
val text2 = ToStringBuilder.reflectionToString(obj, new MultilineRecursiveToStringStyle())
println(text2)
console
Outer@7c49cd0c[
  title=タイトル,
  note=scala.collection.immutable.$colon$colon@772294c7[
    head=Inner@8acd465[
      no=1,
      memo=いろは
    ],
    tl=scala.collection.immutable.$colon$colon@7d64ef3e[
      head=Inner@1e03c8f9[
        no=2,
        memo=にほへと
      ],
      tl=scala.collection.immutable.$colon$colon@10f69849[
        head=Inner@7e9769ce[
          no=3,
          memo=ちりぬるを
        ],
        tl=scala.collection.immutable.Nil$@24d0643d[

        ]
      ]
    ]
  ]
]

サンプルコード

PrettyPrintApp.scala
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;

object PrettyPrintApp extends App {

  val obj = Outer("タイトル", Inner(1, "いろは") :: Inner(2, "にほへと")  :: Inner(3, "ちりぬるを") :: Nil)

  println("--------------------------------------------------------------------------------")

  println("obj: ")
  println(obj)

  println("--------------------------------------------------------------------------------")

  println("ToStringStyle.MULTI_LINE_STYLE: ")
  val text1 = ToStringBuilder.reflectionToString(obj, ToStringStyle.MULTI_LINE_STYLE)
  println(text1)

  println("--------------------------------------------------------------------------------")

  println("MultilineRecursiveToStringStyle: ")
  val text2 = ToStringBuilder.reflectionToString(obj, new MultilineRecursiveToStringStyle())
  println(text2)

  println("--------------------------------------------------------------------------------")

}


case class Outer(title: String, note: Seq[Inner])
case class Inner(no: Int, memo: String)