Skip to the content.

Encoder and Decoder derivation

At the moment supported only for Scala 2.

libraryDependencies += "com.github.geirolz" %% "cats-xml-generic" % "0.0.15"

XmlTypeInterpreter

XmlTypeInterpreter is used to map fields and get the xml type and label. By default using XmlTypeInterpreter.default[T] or using it implicitly

Derivation

Given

case class ValueClass(value: String) extends AnyVal
case class Bar(field1: String, field2: BigDecimal)
case class Foo(
  primitiveField: Double = 666d,
  valueClass: ValueClass,
  bar: Bar,
  missingField: Option[String],
  missingNode: Option[Bar]
)

Decoder semiauto

import cats.xml.XmlNode
import cats.xml.codec.Decoder
import cats.xml.generic.{XmlElemType, XmlTypeInterpreter}

import cats.xml.syntax.*
import cats.xml.generic.decoder.semiauto.*

implicit val typeInterpreterFoo: XmlTypeInterpreter[Foo] =
  XmlTypeInterpreter
          .default[Foo]
          .overrideType(
            _.param(_.valueClass) -> XmlElemType.Attribute
          )
// typeInterpreterFoo: XmlTypeInterpreter[Foo] = cats.xml.generic.XmlTypeInterpreter$$anon$1@3adc38c7

implicit val decoderValueClass: Decoder[ValueClass] = deriveDecoder[ValueClass]
// decoderValueClass: Decoder[ValueClass] = cats.xml.codec.Decoder$$anonfun$of$2@78a62633
implicit val decoderBar: Decoder[Bar] = deriveDecoder[Bar]
// decoderBar: Decoder[Bar] = cats.xml.codec.Decoder$$anonfun$of$2@2d8b4916
implicit val decoderFoo: Decoder[Foo] = deriveDecoder[Foo]
// decoderFoo: Decoder[Foo] = cats.xml.codec.Decoder$$anonfun$of$2@253a6def

XmlNode("foo")
        .withAttrs(
          "primitiveField" := 1d,
          "valueClass" := "TEST"
        )
        .withChildren(
          XmlNode("bar")
                  .withAttrs(
                    "field1" := "BHO",
                    "field2" := BigDecimal(100)
                  )
        )
        .as[Foo]
// res1: Decoder.Result[Foo] = Valid(Foo(1.0,ValueClass(TEST),Bar(BHO,100),None,None))

Encoder semiauto

import cats.xml.codec.Encoder
import cats.xml.generic.{XmlElemType, XmlTypeInterpreter}

import cats.xml.syntax.*
import cats.xml.generic.encoder.semiauto.*

implicit val typeInterpreterFoo: XmlTypeInterpreter[Foo] =
  XmlTypeInterpreter
    .default[Foo]
    .overrideType(
      _.param(_.valueClass) -> XmlElemType.Attribute
    )
// typeInterpreterFoo: XmlTypeInterpreter[Foo] = cats.xml.generic.XmlTypeInterpreter$$anon$1@372555cd

implicit val encoderValueClass: Encoder[ValueClass] = deriveEncoder[ValueClass]
// encoderValueClass: Encoder[ValueClass] = cats.xml.codec.DataEncoder$$anonfun$of$4@409179c6
implicit val encoderBar: Encoder[Bar]               = deriveEncoder[Bar]
// encoderBar: Encoder[Bar] = cats.xml.codec.Encoder$$anonfun$of$2@3632212e
implicit val encoderFoo: Encoder[Foo]               = deriveEncoder[Foo]
// encoderFoo: Encoder[Foo] = cats.xml.codec.Encoder$$anonfun$of$2@1370cb6c

Foo(
  primitiveField = 1d,
  valueClass     = ValueClass("TEST"),
  bar            = Bar("BHO", BigDecimal(100)),
  missingField   = None,
  missingNode    = None
).toXml
// res2: cats.xml.Xml = <Foo primitiveField="1.0" valueClass="TEST">
//  <Bar field1="BHO" field2="100"/>
// </Foo>