【Scala】ネストされているclassをcirceでencodeする際にビルドエラー

## 概要
circeはScalaで使用できるJSONのパース用ライブラリです。[Akka HTTP + circe + Flywayを用いた雑なHTTPサーバのサンプルと解説](https://yoshinorin.net/2019/04/01/akkahttp-example/)の記事にある通り、AkkaHTTPで使用されているイメージがあります。
今回はこのcirceで、ネストがあるclassをencodeする時に少しハマったのでメモ書きを残しておきます。

## エラー内容
まず、今回JSONにencodeする対象のclassは以下とします。`InitialResponse`の配下に`CompanyResponse`のclassがいる構成になっています。

```scala:InitialResponse.scala
case class InitialResponse
(
  byNpmrSortCompanies: Seq[CompanyResponse], // 売上高当期純利益率順
  byEquityRatioCompanies: Seq[CompanyResponse], // 純資産比率順
  byRoaCompanies: Seq[CompanyResponse], // ROA順
  byRoeCompanies: Seq[CompanyResponse], // ROE順
)
```

```scala:CompanyResponse.scala
case class CompanyResponse
(
  companyId: String,
  companyName: String,
  address: String, // 住所
  accountingPeriod: String, // 決算期
  salesAmount: BigInt, // 売上高
  netIncome: BigInt, // 当期純利益
  totalAssets: BigInt, // 総資産
  netAssets: BigInt, // 純資産
  employees: BigInt, // 従業員数
  npmr: BigDecimal, // 売上高当期純利益率
  roa: BigDecimal, // ROA
  roe: BigDecimal, // ROE
  equityRatio: BigDecimal, // 純資産比率
  salesPerEmployee: BigInt, // 一人当たり売上高
)
```

さて、この構成で`InitialResponse`を以下のようなコードにて、JSONにencodeするとどうなるか。ビルド時に`could not find Lazy implicit value of type io.circe.generic.encoding.DerivedAsObjectEncoder`というエラーが発生します。

```scala
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives.{complete, failWith}
import akka.http.scaladsl.server.StandardRoute
import companyInfo.model.api.{CompanyResponse, InitialResponse}
import companyInfo.useCase.CompanySearchUseCase
import io.circe.Encoder
import io.circe.generic.semiauto.deriveEncoder
import io.circe.syntax._

object CompanySearchController {

  implicit val encodeInitialResponse: Encoder[InitialResponse] = deriveEncoder[InitialResponse]

  def getInitialCompanyFetch(): StandardRoute = {

    // InitialResponseのオブジェクトを取得（内容は割愛）
    CompanySearchUseCase.getInitialDisplayCompanyInfo() match {
      case Left(ex) => failWith(ex)
      // InitialResponse型
      case Right(initialRes) =>
        // 受け取ったオブジェクトをJSONにencode
        val res = initialRes.asJson
        complete(HttpEntity(
          ContentTypes.`application/json`,
          s"$res"
        ))
    }
  }
}
```

## 対応
原因は、Encoderに`InitialResponse`しか設定していないことです。ネストしているclassについては、その子のclassのEncoderも定義する必要があります。
ということで、以下のように`CompanyResponse`のEncoderを追加すれば解消します。なお、全ソースコードは[こちら](https://github.com/someone7140/scala_play/blob/master/company_info_backend/src/main/scala/companyInfo/controller/CompanySearchController.scala)にあります。

```scala
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives.{complete, failWith}
import akka.http.scaladsl.server.StandardRoute
import companyInfo.model.api.{CompanyResponse, InitialResponse}
import companyInfo.useCase.CompanySearchUseCase
import io.circe.Encoder
import io.circe.generic.semiauto.deriveEncoder
import io.circe.syntax._

object CompanySearchController {

  // CompanyResponseのEncoderを追加
  implicit val encodeCompanyResponse: Encoder[CompanyResponse] = deriveEncoder[CompanyResponse]
  implicit val encodeInitialResponse: Encoder[InitialResponse] = deriveEncoder[InitialResponse]

  def getInitialCompanyFetch(): StandardRoute = {

    // InitialResponseのオブジェクトを取得（内容は割愛）
    CompanySearchUseCase.getInitialDisplayCompanyInfo() match {
      case Left(ex) => failWith(ex)
      // InitialResponse型
      case Right(initialRes) =>
        // 受け取ったオブジェクトをJSONにencode
        val res = initialRes.asJson
        complete(HttpEntity(
          ContentTypes.`application/json`,
          s"$res"
        ))
    }
  }
}

```