Aeroless is an extension tools for ReactiveAerospike. It's build above the awesome Shapeless library.
Add in your build.sbt
resolvers += "Tabmo Bintray" at "https://dl.bintray.com/tabmo/maven"
libraryDependencies += "io.tabmo" %% "aeroless" % "0.2"
An AST structure is include in the library to represent Aerospike record :
AsValue.obj(
"name" -> AsString("Romain"),
"age" -> AsLong(27),
"contact" -> AsValue.obj("address" -> AsString("Rue de Thor")),
"friends" -> AsArray(Array(AsString("toto"), AsString("fifou")))
)
You can parse AerospikeRecord to AsValue :
val record: AerospikeRecord = ...
val ast: AsValue = AsValue(record)
And transform AsValue to Sequence of Bin like that :
val value = AsValue.obj(
"name" -> AsString("Romain"),
"age" -> AsLong(27),
"contact" -> AsValue.obj("address" -> AsString("Rue de Thor")),
"friends" -> AsArray(Array(AsString("toto"), AsString("fifou")))
)
val binSeq = value.asObject.toSeqBins //asObject is an unsafe operation
Aeroless provide Encoder and Decoder to transform Scala object from/to raw Aerospike structure.
You can encode complex data type to AsValue :
case class Contact(address: String)
case class Person(name: String, age: Long, contact: Contact, friends: Option[List[String]])
val encodedObject = AsEncoder[Person].encode(Person("Romain", 27, Contact("Rue de Thor"), Some(List("toto", "fifou"))))
encodedObject shouldBe AsValue.obj(
"name" -> AsString("Romain"),
"age" -> AsLong(27),
"contact" -> AsValue.obj("address" -> AsString("Rue de Thor")),
"friends" -> AsArray(Array(AsString("toto"), AsString("fifou")))
)
You can transform encoder with the contramap method :
val booleanEncoder = AsEncoder[Long].contramap[Boolean](b => if (b) 1L else 0L)
booleanEncoder.encode(true) shouldBe AsValue.long(1L)
booleanEncoder.encode(false) shouldBe AsValue.long(0L)
...and decode the same object from AsValue :
val personAs = AsValue.obj(
"name" -> AsString("Romain"),
"age" -> AsLong(27),
"contact" -> AsValue.obj("address" -> AsString("Rue de Thor")),
"friends" -> AsArray(Array(AsString("toto"), AsString("fifou")))
)
AsDecoder[Person].decode(personAs) shouldBe Done(Person("Romain", 27, Contact("Rue de Thor"), Some(List("toto", "fifou"))))
You can transform decoder with the map method :
val booleanDecoder = AsDecoder[Long].map(l => if (l > 0) true else false)
booleanDecoder.decode(AsValue.long(1L)) shouldBe Done(true)
booleanDecoder.decode(AsValue.long(0L)) shouldBe Done(false)
You can decoder sub value of AsObject with apply method :
val value = AsValue.obj(
"age" -> AsLong(27)
).asObject
value[Long]("age") shouldBe Done(27)
and use for expression :
case class Param2(p: String)
val obj: AsObject = ...
for {
param1 <- obj[Long]("param1")
param2 <- obj[Param2]("param2")
} yield (param1, param2)
A support for this type is available. For example, just look on the tests!