pbson is a BSON scala library.
The goal of this library is to create at compile-time the boilerplate necessary to encode and decode of a
certain type.
The pbson provides generic codec derivation using Shapeless.
This library provides another way encode and decode case classes for
mongo scala driver.
Decoder instead of throw Exception return Either[BsonError, T]
pbson can derive bson encoder and decoder:
BsonEncoder[T] : T => BsonValue
BsonDecoder[T] : BsonValue => Either[BsonError, T]
Quick Start
If you're using SBT, add the following line to your build file:
libraryDependencies += "ru.twistedlogic" %% "pbson" % "0.0.20"
Link
to code
import pbson._
import pbson.semiauto._
case class MyId(value: String) extends AnyVal
case class TestCase(a: Int, b: Option[String], id: MyId)
implicit val testCaseEncoder: BsonEncoder[TestCase] = deriveEncoder
implicit val testCaseDecoder: BsonDecoder[TestCase] = deriveDecoder
val test = TestCase(3, Some("45"), MyId("000"))
val bson = test.toBson
println(bson)
// { "a" : 3, "b" : "45", "id" : "000" }
println(bson.fromBson[TestCase]())
// Right(TestCase(3,Some(45),MyId(000)))
AnyVal wrappers
AnyVal wrappers encode and decode as value.
Link
to code
case class MyId(value: String) extends AnyVal
implicit val testCaseEncoder: BsonEncoder[MyId] = deriveEncoder
implicit val testCaseDecoder: BsonDecoder[MyId] = deriveDecoder
val test = MyId("000")
val bson = test.toBson
println(bson)
// BsonString{value='000'}
println(bson.fromBson[MyId]())
// Right(MyId(000))
ADT (Algebraic Data Types)
semiauto
Link
to code
sealed trait ADT
object ADT {
case class A(s: String) extends ADT
case class B(a: Int) extends ADT
}
import ADT._
implicit val adtEncoder: BsonEncoder[ADT] = deriveEncoder
implicit val adtDecoder: BsonDecoder[ADT] = deriveDecoder
val test : ADT = B(4)
val bson = test.toBson
println(bson)
// { "a" : 4, "type" : "B" }
println(bson.fromBson[ADT])
// Right(B(4))
manual enumeration
Link
to code
sealed trait ADT
object ADT {
final case object A extends ADT
final case object B extends ADT
}
import ADT._
implicit val adtEnumEncoder: BsonEncoder[ADT] = asStringEncoder {
case A => "A"
case B => "B"
}
implicit val adtEnumDecoder: BsonDecoder[ADT] = asStringDecoder {
case "A" => A
case "B" => B
}
val test : ADT = B
val bson = test.toBson
println(bson)
// BsonString{value='B'}
println(bson.fromBson[ADT])
// Right(B)
Map
as object
Link
to code
case class TestCase(a: Map[String, String])
implicit val testCaseEncoder: BsonEncoder[TestCase] = deriveEncoder
implicit val testCaseDecoder: BsonDecoder[TestCase] = deriveDecoder
val test : TestCase = TestCase(Map("key1" -> "value1", "key2" -> "value2"))
val bson = test.toBson
println(bson)
// { "a" : { "key1" : "value1", "key2" : "value2" } }
println(bson.fromBson[TestCase])
// Right(TestCase(Map(key1 -> value1, key2 -> value2)))
map as array
Link
to code
case class TestCase(a: Map[String, String])
implicit val testCaseEncoder: BsonEncoder[TestCase] = deriveEncoder
implicit val testCaseDecoder: BsonDecoder[TestCase] = deriveDecoder
implicit val mapEncoder: ReprBsonMaybeEncoder[Map[String, String]] = map2ArrayEncoder
implicit val mapDecoder: BsonDecoder[Map[String, String]] = array2MapDecoder
val test : TestCase = TestCase(Map("key1" -> "value1", "key2" -> "value2"))
val bson = test.toBson
println(bson)
// { "a" : [{ "_v" : "value1", "_k" : "key1" }, { "_v" : "value2", "_k" : "key2" }] }
println(bson.fromBson[TestCase])
// Right(TestCase(Map(key1 -> value1, key2 -> value2)))
map (key, value case classes) as array
Link
to code
case class Key(k: String)
case class Value(v: String)
case class TestCase(a: Map[Key, Value])
implicit val mapEncoder: ReprBsonMaybeEncoder[Map[Key, Value]] = map2ArrayEncoder
implicit val mapDecoder: BsonDecoder[Map[Key, Value]] = array2MapDecoder
implicit val testCaseEncoder: BsonEncoder[TestCase] = deriveEncoder
implicit val testCaseDecoder: BsonDecoder[TestCase] = deriveDecoder
val test : TestCase = TestCase(Map(Key("45") -> Value("34"), Key("23") -> Value("45")))
val bson = test.toBson
println(bson)
// { "a" : [{ "v" : "34", "k" : "45" }, { "v" : "45", "k" : "23" }] }
println(bson.fromBson[TestCase])
// Right(TestCase(Map(Key(45) -> Value(34), Key(23) -> Value(45))))
Enumeration
Link
to code
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
implicit val weekDayEncoder: BsonEncoder[WeekDay.Value] = enumEncoder(WeekDay)
implicit val weekDayDecoder: BsonDecoder[WeekDay.Value] = enumDecoder(WeekDay)
val test : WeekDay.Value = WeekDay.Thu
val bson = test.toBson
println(bson)
// BsonString{value='Thu'}
println(bson.fromBson[WeekDay.Value])
// Right(Thu)
Cursor
Link
to code
val doc = BsonDocument(
"a" -> BsonDocument(
"a" -> BsonInt64(4l),
"b" -> BsonArray(BsonString("45"), BsonString("23"))
),
"b" -> BsonArray(BsonString("45"), BsonString("23"))
)
val av = doc.cursor().down("a").get[Long]("a")
println(av)
// Right(4)