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



コメントで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の値を整形して表示します。

```scala: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:console
Outer(タイトル,List(Inner(1,いろは), Inner(2,にほへと), Inner(3,ちりぬるを)))
```

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

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

```scala:code
val text1 = ToStringBuilder.reflectionToString(obj, ToStringStyle.MULTI_LINE_STYLE)
println(text1)
```

```console: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型になっているフィールドの中身まで再帰的に整形する事ができます。

```scala:code
val text2 = ToStringBuilder.reflectionToString(obj, new MultilineRecursiveToStringStyle())
println(text2)
```

```console: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[
          
        ]
      ]
    ]
  ]
]
```

## サンプルコード

```scala: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)


```