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)