Given a case class like:
case class SignerListNode(
flags: Long,
ownerNode: Option[String],
previousTxnId: Option[TxnHash],
previousTxnLgrSeq: Option[LedgerSequence],
signerEntries: List[SignerEntry],
signerListID: Long,
signerQuorum: Long,
index: LedgerHash
) extends LedgerNode
With JSON encoding like:
"Flags" : 65536,
"OwnerNode" : "0000000000000000",
"PreviousTxnId" : null,
"PreviousTxnLgrSeq" : 141336,
"SignerEntries" : [
{
"SignerEntry" : {
"Account" : "rsztqq2m9LfJskJAk8CX15twh284LcAB8y",
"SignerWeight" : 1
}
},
{
"SignerEntry" : {
"Account" : "rfZxEoKbksnFQHV4HqSCdtWU2Tbk72U2gk",
"SignerWeight" : 1
}
},
{
"SignerEntry" : {
"Account" : "r9hQZzGo26ZB59huqxDT6DBwbVk6FssToe",
"SignerWeight" : 1
}
},
{
"SignerEntry" : {
"Account" : "rwyB6f2ZfFmCqMmnxBAWaJc8URzWJv9ktX",
"SignerWeight" : 1
}
},
{
"SignerEntry" : {
"Account" : "rGcFwUAo9y8zV2wfimqAnfNAPWQUgXKER3",
"SignerWeight" : 1
}
}
],
"SignerListID" : 0,
"SignerQuorum" : 5,
"index" : "00BA02629B50C964D6481C23121058A80B55AA496FA5C6333D49FB836E72E19B"
}
object SignerListNode extends CirceCodecUtils {
implicit val config: Configuration = configCapitalizeExcept(Set("index"))
private implicit val unwrapper: Decoder[List[SignerEntry]] =
Decoder.decodeList[SignerEntry](Decoder[SignerEntry].prepare(_.downField("SignerEntry")))
private implicit val wrapper: Encoder[List[SignerEntry]] =
Encoder.encodeList[SignerEntry](
Encoder.AsObject[SignerEntry].mapJsonObject(b => JsonObject.singleton("SignerEntry", b.asJson))
)
implicit val codec: Codec.AsObject[SignerListNode] = deriveConfiguredCodec[SignerListNode]
}
Can be generalized with:
def wrapListOfNestedObj[A: Codec.AsObject](name: String): Codec[List[A]] = {
val unwrapper: Decoder[List[A]] = Decoder.decodeList[A](Decoder[A].prepare(_.downField(name)))
val wrapper: Encoder[List[A]] = Encoder.encodeList[A](
Encoder.AsObject[A].mapJsonObject(b => JsonObject.singleton(name, b.asJson))
)
Codec.from(unwrapper, wrapper)
}
object SignerListNode extends CirceCodecUtils {
implicit val config: Configuration = configCapitalizeExcept(Set("index"))
private implicit val cowrapper: Codec[List[SignerEntry]] = wrapListOfNestedObj[SignerEntry]("SignerEntry")
implicit val codec: Codec.AsObject[SignerListNode] = deriveConfiguredCodec[SignerListNode]
}