Skip to content

Commit 178e78d

Browse files
committed
customized deploy, added pull request codahale#42
1 parent e648056 commit 178e78d

5 files changed

Lines changed: 54 additions & 11 deletions

File tree

pom.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
<groupId>com.codahale</groupId>
1212
<artifactId>jerkson_2.9.1</artifactId>
13-
<version>0.6.0-SNAPSHOT</version>
13+
<version>0.6.0-Matygo</version>
1414
<name>Jerkson for Scala</name>
1515

1616
<properties>
@@ -47,8 +47,9 @@
4747

4848
<distributionManagement>
4949
<repository>
50-
<id>repo.codahale.com</id>
51-
<url>scp://codahale.com/home/codahale/repo.codahale.com</url>
50+
<id>matygo</id>
51+
<name>Matygo Releases</name>
52+
<url>http://office.matygo.com:8081/nexus/content/repositories/matygo/</url>
5253
</repository>
5354
</distributionManagement>
5455

src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class CaseClassDeserializer(config: DeserializationConfig,
1515
classLoader: ClassLoader) extends JsonDeserializer[Object] {
1616
private val isSnakeCase = javaType.getRawClass.isAnnotationPresent(classOf[JsonSnakeCase])
1717
private val params = CaseClassSigParser.parse(javaType.getRawClass, config.getTypeFactory, classLoader).map {
18-
case (name, jt) => (if (isSnakeCase) snakeCase(name) else name, jt)
18+
case (name, jt, defaultValue) => (if (isSnakeCase) snakeCase(name) else name, jt, defaultValue)
1919
}.toArray
2020
private val paramTypes = params.map { _._2.getRawClass }.toList
2121
private val constructor = javaType.getRawClass.getConstructors.find { c =>
@@ -48,7 +48,7 @@ class CaseClassDeserializer(config: DeserializationConfig,
4848
val node = jp.readValueAsTree[JsonNode]
4949

5050
val values = new ArrayBuffer[AnyRef]
51-
for ((paramName, paramType) <- params) {
51+
for ((paramName, paramType, paramDefault) <- params) {
5252
val field = node.get(paramName)
5353
val tp = new TreeTraversingParser(if (field == null) NullNode.getInstance else field, jp.getCodec)
5454
val value = if (paramType.getRawClass == classOf[Option[_]]) {
@@ -60,6 +60,12 @@ class CaseClassDeserializer(config: DeserializationConfig,
6060

6161
if (field != null || value != null) {
6262
values += value
63+
} else {
64+
// see if a default value was supplied
65+
paramDefault match {
66+
case Some(v) => values += v
67+
case None =>
68+
}
6369
}
6470

6571

src/main/scala/com/codahale/jerkson/util/CaseClassSigParser.scala

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ object CaseClassSigParser {
5151
protected def simpleName(klass: Class[_]) =
5252
klass.getName.split("\\$").last
5353

54+
implicit def class2companion(clazz: Class[_]) = new {
55+
def companionClass(classLoader: ClassLoader): Class[_] = {
56+
val path = if (clazz.getName.endsWith("$")) clazz.getName else "%s$".format(clazz.getName)
57+
Some(Class.forName(path, true, classLoader)).getOrElse {
58+
throw new Error("Could not resolve clazz='%s'".
59+
format(path))
60+
}
61+
}
62+
63+
def companionObject(classLoader: ClassLoader) = companionClass(classLoader).getField("MODULE$").get(null)
64+
}
65+
5466
protected def findSym[A](clazz: Class[A], classLoader: ClassLoader) = {
5567
val name = simpleName(clazz)
5668
val pss = parseScalaSig(clazz, classLoader)
@@ -81,12 +93,26 @@ object CaseClassSigParser {
8193

8294
def parse[A](clazz: Class[A], factory: TypeFactory, classLoader: ClassLoader) = {
8395
findSym(clazz, classLoader).children.filter(c => c.isCaseAccessor && !c.isPrivate)
84-
.flatMap { ms =>
96+
.zipWithIndex.map { case (ms,idx) => {
8597
ms.asInstanceOf[MethodSymbol].infoType match {
86-
case NullaryMethodType(t: TypeRefType) => ms.name -> typeRef2JavaType(t, factory, classLoader) :: Nil
98+
case NullaryMethodType(t: TypeRefType) => {
99+
100+
// try and find the field's default
101+
val companionClass = clazz.companionClass(classLoader)
102+
val companionObject = clazz.companionObject(classLoader)
103+
val defaultMethod = try {
104+
Some(companionClass.getMethod("apply$default$%d".format(idx + 1)))
105+
}
106+
catch {
107+
case _ => None // indicates no default value was supplied
108+
}
109+
val defaultValue = defaultMethod.map(m => Some(m.invoke(companionObject))).getOrElse(None)
110+
111+
Tuple3(ms.name, typeRef2JavaType(t, factory, classLoader), defaultValue) :: Nil
112+
}
87113
case _ => Nil
88114
}
89-
}
115+
}}.flatten
90116
}
91117

92118
protected def typeRef2JavaType(ref: TypeRefType, factory: TypeFactory, classLoader: ClassLoader): JavaType = {

src/test/scala/com/codahale/jerkson/tests/CaseClassSupportSpec.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package com.codahale.jerkson.tests
33
import com.codahale.jerkson.Json._
44
import com.codahale.simplespec.Spec
55
import com.codahale.jerkson.ParsingException
6-
import com.fasterxml.jackson.databind.node.IntNode
76
import org.junit.Test
7+
import com.fasterxml.jackson.databind.node.IntNode
88

99
class CaseClassSupportSpec extends Spec {
1010
class `A basic case class` {
@@ -27,6 +27,13 @@ class CaseClassSupportSpec extends Spec {
2727
}
2828
}
2929

30+
class `A case class with a default field` {
31+
@Test def `is parsable from an incomplete JSON object` = {
32+
parse[CaseClassWithDefaultString]("""{"id":1}""").must(be(CaseClassWithDefaultString(1, "Coda")))
33+
parse[CaseClassWithDefaultInt]("""{"id":1}""").must(be(CaseClassWithDefaultInt(1, 42)))
34+
}
35+
}
36+
3037
class `A case class with lazy fields` {
3138
@Test def `generates a JSON object with those fields evaluated` = {
3239
generate(CaseClassWithLazyVal(1)).must(be("""{"id":1,"woo":"yeah"}"""))

src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.codahale.jerkson.tests
22

3-
import com.fasterxml.jackson.databind.JsonNode
4-
import com.fasterxml.jackson.annotation.{JsonIgnoreProperties, JsonIgnore}
53
import com.codahale.jerkson.JsonSnakeCase
4+
import com.fasterxml.jackson.annotation.{JsonIgnoreProperties, JsonIgnore}
5+
import com.fasterxml.jackson.databind.JsonNode
66

77
case class CaseClass(id: Long, name: String)
88

9+
case class CaseClassWithDefaultString(id: Long, name: String = "Coda")
10+
case class CaseClassWithDefaultInt(id: Long, answer: Int = 42)
11+
912
case class CaseClassWithLazyVal(id: Long) {
1013
lazy val woo = "yeah"
1114
}

0 commit comments

Comments
 (0)