All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.module.scala.deser.TupleDeserializerModule.scala Maven / Gradle / Ivy

package com.fasterxml.jackson.module.scala.deser

import com.fasterxml.jackson.module.scala.JacksonModule
import org.codehaus.jackson.`type`.JavaType
import org.codehaus.jackson.map.{JsonDeserializer, BeanProperty, BeanDescription, DeserializerProvider, DeserializationConfig, DeserializationContext, Deserializers}
import org.codehaus.jackson.map.deser.std.StdDeserializer
import java.lang.IllegalStateException
import org.codehaus.jackson.{JsonToken, JsonParser}

private class TupleDeserializer(javaType: JavaType,
                                config: DeserializationConfig,
                                provider: DeserializerProvider,
                                property: BeanProperty)
  extends StdDeserializer[Product](classOf[Product]) {

  val cls = javaType.getRawClass
  val ctors = cls.getConstructors
  if (ctors.length > 1) throw new IllegalStateException("Tuple should have only one constructor")
  val ctor = ctors.head
  val paramTypes = for (i <- 0 until javaType.containedTypeCount()) yield javaType.containedType(i)

  val paramDesers = paramTypes map { paramType =>
    provider.findValueDeserializer(config, paramType, property)
  }

  def deserialize(jp: JsonParser, ctxt: DeserializationContext) = {
    // Ok: must point to START_ARRAY (or equivalent)
    if (!jp.isExpectedStartArrayToken) {
      throw ctxt.mappingException(javaType.getRawClass)
    }

    val params = paramDesers map { deser =>
      jp.nextToken()
      deser.deserialize(jp, ctxt)
    }

    ctor.newInstance(params: _*).asInstanceOf[Product]
  }

}

private object TupleDeserializerResolver extends Deserializers.Base {

  def PRODUCT = classOf[Product]

  override def findBeanDeserializer(javaType: JavaType,
                                    config: DeserializationConfig,
                                    provider: DeserializerProvider,
                                    beanDesc: BeanDescription,
                                    property: BeanProperty): JsonDeserializer[_] = {
    val cls = javaType.getRawClass
    if (!PRODUCT.isAssignableFrom(cls)) null else
    // If it's not *actually* a tuple, it's either a case class or a custom Product
    // which either way we shouldn't handle here.
    if (!cls.getName.startsWith("scala.Tuple")) null else
    new TupleDeserializer(javaType, config, provider, property)
  }
}

/**
 * Adds deserialization support for Scala Tuples.
 */
trait TupleDeserializerModule extends JacksonModule {
  this += TupleDeserializerResolver
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy