Skip to content

Commit d22f419

Browse files
authored
Added support for type aliases in the CaseClassCodec. (mongodb#39)
SCALA-305
1 parent fcc18ef commit d22f419

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

bson/src/main/scala/org/mongodb/scala/bson/codecs/macrocodecs/CaseClassCodec.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ private[codecs] object CaseClassCodec {
109109
* Removes Option type as the Option value is wrapped automatically below.
110110
* Throws if the case class contains a Tuple
111111
*
112-
* @param t the type to flatten the arguments for
112+
* @param at the type to flatten the arguments for
113113
* @return a list of the type arguments for the type
114114
*/
115-
def flattenTypeArgs(t: Type): List[c.universe.Type] = {
115+
def flattenTypeArgs(at: Type): List[c.universe.Type] = {
116+
val t = at.dealias
116117
val typeArgs = if (isMap(t)) {
117118
if (t.typeArgs.head != stringType) c.abort(c.enclosingPosition, "Maps must contain string types for keys")
118119
t.typeArgs.tail

bson/src/test/scala/org/mongodb/scala/bson/codecs/MacrosSpec.scala

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ class MacrosSpec extends FlatSpec with Matchers {
8888
case class UnsupportedTuple(value: (String, String))
8989
case class UnsupportedMap(value: Map[Int, Int])
9090

91+
type SimpleTypeAlias = Map[String, String]
92+
case class ContainsSimpleTypeAlias(a: String, b: SimpleTypeAlias = Map.empty)
93+
type CaseClassTypeAlias = Person
94+
case class ContainsCaseClassTypeAlias(a: String, b: CaseClassTypeAlias)
95+
type ADTCaseClassTypeAlias = ContainsADT
96+
case class ContainsADTCaseClassTypeAlias(a: String, b: ADTCaseClassTypeAlias)
97+
9198
"Macros" should "be able to round trip simple case classes" in {
9299
roundTrip(Empty(), "{}", classOf[Empty])
93100
roundTrip(Person("Bob", "Jones"), """{firstName: "Bob", lastName: "Jones"}""", classOf[Person])
@@ -174,16 +181,8 @@ class MacrosSpec extends FlatSpec with Matchers {
174181
it should "support ADT sealed case classes" in {
175182
val leaf = Leaf(1)
176183
val branch = Branch(Branch(Leaf(1), Leaf(2), 3), Branch(Leaf(4), Leaf(5), 6), 3) // scalastyle:ignore
177-
178-
def createJson(tree: Tree): String = {
179-
tree match {
180-
case l: Leaf => s"""{_t: "Leaf", value: ${l.value}}"""
181-
case b: Branch => s"""{_t: "Branch", b1: ${createJson(b.b1)}, b2: ${createJson(b.b2)}, value: ${b.value}}"""
182-
case _ => "{}"
183-
}
184-
}
185-
val leafJson = createJson(leaf)
186-
val branchJson = createJson(branch)
184+
val leafJson = createTreeJson(leaf)
185+
val branchJson = createTreeJson(branch)
187186

188187
roundTrip(leaf, leafJson, classOf[Tree])
189188
roundTrip(branch, branchJson, classOf[Tree])
@@ -207,6 +206,17 @@ class MacrosSpec extends FlatSpec with Matchers {
207206
roundTrip(nodeB, nodeBJson, classOf[Graph])
208207
}
209208

209+
it should "support type aliases in case classes" in {
210+
roundTrip(ContainsSimpleTypeAlias("c", Map("d" -> "c")), """{a: "c", b: {d: "c"}}""", classOf[ContainsSimpleTypeAlias])
211+
roundTrip(ContainsCaseClassTypeAlias("c", Person("Tom", "Jones")), """{a: "c", b: {firstName: "Tom", lastName: "Jones"}}""",
212+
classOf[ContainsCaseClassTypeAlias], classOf[CaseClassTypeAlias])
213+
214+
val branch = Branch(Branch(Leaf(1), Leaf(2), 3), Branch(Leaf(4), Leaf(5), 6), 3) // scalastyle:ignore
215+
val branchJson = createTreeJson(branch)
216+
roundTrip(ContainsADTCaseClassTypeAlias("c", ContainsADT("Tom", branch)), s"""{a: "c", b: {name: "Tom", tree: $branchJson}}""",
217+
classOf[ContainsADTCaseClassTypeAlias], classOf[ADTCaseClassTypeAlias], classOf[Tree])
218+
}
219+
210220
it should "support throw a CodecConfigurationException missing _t field" in {
211221
val missing_t = """{name: "nodeA", value: null}"""
212222
val registry = CodecRegistries.fromRegistries(CodecRegistries.fromProviders(classOf[Graph]), DEFAULT_CODEC_REGISTRY)
@@ -278,4 +288,12 @@ class MacrosSpec extends FlatSpec with Matchers {
278288

279289
val documentCodec: Codec[Document] = DEFAULT_CODEC_REGISTRY.get(classOf[Document])
280290

291+
def createTreeJson(tree: Tree): String = {
292+
tree match {
293+
case l: Leaf => s"""{_t: "Leaf", value: ${l.value}}"""
294+
case b: Branch => s"""{_t: "Branch", b1: ${createTreeJson(b.b1)}, b2: ${createTreeJson(b.b2)}, value: ${b.value}}"""
295+
case _ => "{}"
296+
}
297+
}
298+
281299
}

docs/reference/content/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Changes between released versions
1212

1313
### 2.1.0
1414

15+
* Added support for type aliases in the CaseClassCodec. [SCALA-305](https://jira.mongodb.org/browse/SCALA-305)
1516
* Added the ability to ignore `None` values when encoding `Option` fields. [SCALA-300](https://jira.mongodb.org/browse/SCALA-300)
1617
* Added the ability to handle missing values for `Option` fields. [SCALA-299](https://jira.mongodb.org/browse/SCALA-299)
1718
* Improved the CaseClassCodec handling of `null` values. [SCALA-301](https://jira.mongodb.org/browse/SCALA-301)

0 commit comments

Comments
 (0)