Skip to content

Commit

Permalink
add ScalaObjectDeserializerModule
Browse files Browse the repository at this point in the history
  • Loading branch information
pjfanning committed Sep 3, 2021
1 parent b7731a5 commit 2e7596a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.fasterxml.jackson.module.scala.deser

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.deser.Deserializers
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind._
import com.fasterxml.jackson.module.scala.JacksonModule
import com.fasterxml.jackson.module.scala.util.ClassW

import scala.languageFeature.postfixOps

private class ScalaObjectDeserializer(clazz: Class[_]) extends StdDeserializer[Any](classOf[Any]) {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): Any = {
clazz.getDeclaredFields.find(_.getName == "MODULE$").map(_.get(null)).getOrElse(null)
}
}

private object ScalaObjectDeserializerResolver extends Deserializers.Base {
override def findBeanDeserializer(javaType: JavaType, config: DeserializationConfig, beanDesc: BeanDescription): JsonDeserializer[_] = {
val clazz = javaType.getRawClass
if (ClassW(clazz).isScalaObject)

This comment has been minimized.

Copy link
@marcinbelicki

marcinbelicki Dec 13, 2022

If I'm reading correctly method isScalaObject already checks if clazz has declaredField "MODULE$". So I think it's not necessary to repeat that in line 14 🤔

This comment has been minimized.

Copy link
@pjfanning

pjfanning Dec 13, 2022

Author Member

if you want to try to change this, do you want to try to make the change yourself and submit a PR?

This comment has been minimized.

Copy link
@marcinbelicki

marcinbelicki Nov 29, 2023

Sorry for the late response. I was trying to implement my approach:
image
and the ScalaObject object with unapply method
image
But i do not have access to make and commit to new branch. Is there some way to gain the required permissions or do I have to do this other way?

This comment has been minimized.

Copy link
@pjfanning

pjfanning Nov 30, 2023

Author Member

fork https://github.com/FasterXML/jackson-module-scala and commit to a branch on your own fork - you can create Pull Requests for this git repo based on a branch in your fork.

new ScalaObjectDeserializer(clazz)
else null
}
}

trait ScalaObjectDeserializerModule extends JacksonModule {
this += { _ addDeserializers ScalaObjectDeserializerResolver }
}

object ScalaObjectDeserializerModule extends ScalaObjectDeserializerModule
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.fasterxml.jackson.module.scala.deser

import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule, ScalaObjectMapper}
import com.fasterxml.jackson.module.scala.deser.CaseObjectDeserializerTest.TestObject

object CaseObjectDeserializerTest {
case object TestObject
}

class CaseObjectDeserializerTest extends DeserializerTest {
def module = DefaultScalaModule

"An ObjectMapper with DefaultScalaModule and ScalaObjectDeserializerModule" should "deserialize a case object and not create a new instance" in {
val mapper = JsonMapper.builder().addModule(DefaultScalaModule).addModule(ScalaObjectDeserializerModule).build()
val original = TestObject
val json = mapper.writeValueAsString(original)
val deserialized = mapper.readValue(json, TestObject.getClass)
assert(deserialized == original)
}

"An ObjectMapper with ClassTagExtensions and ScalaObjectDeserializerModule" should "deserialize a case object and not create a new instance" in {
val mapper = JsonMapper.builder()
.addModule(DefaultScalaModule)
.addModule(ScalaObjectDeserializerModule)
.build() :: ClassTagExtensions
val original = TestObject
val json = mapper.writeValueAsString(original)
val deserialized = mapper.readValue[TestObject.type](json)
assert(deserialized == original)
}

"An ObjectMapper with ScalaObjectMapper and ScalaObjectDeserializerModule" should "deserialize a case object and not create a new instance" in {
val mapper = JsonMapper.builder()
.addModule(DefaultScalaModule)
.addModule(ScalaObjectDeserializerModule)
.build() :: ScalaObjectMapper
val original = TestObject
val json = mapper.writeValueAsString(original)
val deserialized = mapper.readValue[TestObject.type](json)
assert(deserialized == original)
}

"An ObjectMapper with DefaultScalaModule but not ScalaObjectDeserializerModule" should "deserialize a case object but create a new instance" in {
val mapper = JsonMapper.builder().addModule(DefaultScalaModule).build()
val original = TestObject
val json = mapper.writeValueAsString(original)
val deserialized = mapper.readValue(json, TestObject.getClass)
assert(deserialized != original)
}

}

0 comments on commit 2e7596a

Please sign in to comment.