Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Add @JsonNoJerkson to pass serdes through to jackson #66

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/com/codahale/jerkson/JsonNoJerkson.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.codahale.jerkson;

import com.fasterxml.jackson.annotation.JacksonAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marker annotation which indicates that the annotated class should not be
* serialized and deserialized using jerkson, and should be passed through to
* jackson instead.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonNoJerkson {

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.codahale.jerkson.deser
import com.fasterxml.jackson.databind._
import scala.collection.{Traversable, MapLike, immutable, mutable}
import com.codahale.jerkson.AST.{JNull, JValue}
import com.codahale.jerkson.JsonNoJerkson
import scala.collection.generic.{MapFactory, GenericCompanion}
import com.fasterxml.jackson.databind.deser.Deserializers
import com.fasterxml.jackson.databind.Module.SetupContext
Expand All @@ -11,7 +12,10 @@ class ScalaDeserializers(classLoader: ClassLoader, context: SetupContext) extend
override def findBeanDeserializer(javaType: JavaType, config: DeserializationConfig,
beanDesc: BeanDescription) = {
val klass = javaType.getRawClass
if (klass == classOf[Range] || klass == classOf[immutable.Range]) {
val noJerkson = klass.isAnnotationPresent(classOf[JsonNoJerkson])
if (noJerkson) {
null
} else if (klass == classOf[Range] || klass == classOf[immutable.Range]) {
new RangeDeserializer
} else if (klass == classOf[StringBuilder]) {
new StringBuilderDeserializer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.codahale.jerkson.ser

import com.codahale.jerkson.AST.JValue
import com.codahale.jerkson.JsonNoJerkson
import com.fasterxml.jackson.databind._
import com.fasterxml.jackson.databind.ser.Serializers

class ScalaSerializers extends Serializers.Base {
override def findSerializer(config: SerializationConfig, javaType: JavaType, beanDesc: BeanDescription) = {
val ser: Object = if (classOf[Option[_]].isAssignableFrom(beanDesc.getBeanClass)) {
new OptionSerializer
val noJerkson = javaType.getRawClass.isAnnotationPresent(classOf[JsonNoJerkson])
val ser: Object = if (noJerkson) {
null
} else if (classOf[Option[_]].isAssignableFrom(beanDesc.getBeanClass)) {
new OptionSerializer
} else if (classOf[StringBuilder].isAssignableFrom(beanDesc.getBeanClass)) {
new StringBuilderSerializer
} else if (classOf[collection.Map[_,_]].isAssignableFrom(beanDesc.getBeanClass)) {
Expand Down
33 changes: 31 additions & 2 deletions src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.codahale.jerkson.tests

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.annotation.{JsonIgnoreProperties, JsonIgnore}
import com.codahale.jerkson.JsonSnakeCase
import com.fasterxml.jackson.annotation.{JsonIgnoreProperties, JsonIgnore, JsonProperty, JsonCreator, JsonValue}
import com.codahale.jerkson.{JsonSnakeCase,JsonNoJerkson}

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

Expand Down Expand Up @@ -72,3 +72,32 @@ case class CaseClassWithTwoConstructors(id: Long, name: String) {
case class CaseClassWithSnakeCase(oneThing: String, twoThing: String)

case class CaseClassWithArrays(one: String, two: Array[String], three: Array[Int])

@JsonNoJerkson
case class NoJerksonCaseClass(id: Int, name: String) {
@JsonCreator def this(
@JsonProperty("ID") id: Option[Int],
@JsonProperty("name-thing") name: Option[String],
@JsonProperty("meta") meta: Any
) = this(id.get, name.get)

@JsonValue def toJson = Map(
"ID" -> id,
"name-thing" -> name,
"meta" -> Seq(id, name)
)
}

@JsonNoJerkson
class NoJerksonIterator(var count: Int) extends Iterator[Int] {
def hasNext = true
def next = { count += 1; count - 1 }

@JsonCreator def this(
@JsonProperty("count") count: Option[Int]
) = this(count.get)

@JsonValue def toJson = Map(
"count" -> count
)
}
54 changes: 54 additions & 0 deletions src/test/scala/com/codahale/jerkson/tests/NoJerksonSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.codahale.jerkson.tests

import com.codahale.jerkson.Json._
import com.codahale.jerkson.ParsingException
import com.codahale.simplespec.Spec
import org.junit.Test

class NoJerksonSpec extends Spec {
class `A no-jerkson case class` {
@Test def `generates a JSON object with matching field values` = {
generate(NoJerksonCaseClass(1, "Coda")).must(be("""{"ID":1,"name-thing":"Coda","meta":[1,"Coda"]}"""))
}

@Test def `is parsable from a JSON object with corresponding fields` = {
parse[NoJerksonCaseClass]("""{"ID":1,"name-thing":"Coda"}""").must(be(NoJerksonCaseClass(1, "Coda")))
parse[NoJerksonCaseClass]("""{"ID":1,"name-thing":"Coda","meta":[1,"Coda"]}""").must(be(NoJerksonCaseClass(1, "Coda")))
}

@Test def `is not parsable from a JSON object with extra fields (using default jackson options)` = {
evaluating {
parse[NoJerksonCaseClass]("""{"ID":1,"name-thing":"Coda","meta":[2,"Not Coda"],"derp":100}""")
}.must(throwA[ParsingException])
}

@Test def `is not parsable from an incomplete JSON object` = {
evaluating {
parse[NoJerksonCaseClass]("""{"ID":1}""")
}.must(throwA[ParsingException])
}
}

class `A no-jerkson iterator` {
@Test def `generates a JSON object with matching field values` = {
generate(new NoJerksonIterator(3)).must(be("""{"count":3}"""))
}

@Test def `is parsable from a JSON object with corresponding fields` = {
parse[NoJerksonIterator]("""{"count":3}""").must(beA[NoJerksonIterator])
parse[NoJerksonIterator]("""{"count":3}""").count.must(be(3))
}

@Test def `is not parsable from a JSON object with extra fields (using default jackson options)` = {
evaluating {
parse[NoJerksonIterator]("""{"count":3,"derp":100}""")
}.must(throwA[ParsingException])
}

@Test def `is not parsable from an incomplete JSON object` = {
evaluating {
parse[NoJerksonIterator]("""{}""")
}.must(throwA[ParsingException])
}
}
}