Skip to content

Instantly share code, notes, and snippets.

@odenzo
Last active September 9, 2019 02:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odenzo/afbf7abad2d0d25bd004dda2b82e7adf to your computer and use it in GitHub Desktop.
Save odenzo/afbf7abad2d0d25bd004dda2b82e7adf to your computer and use it in GitHub Desktop.
When a list of items is encoded and decoded as a List of single value JsonObjects

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]

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment