Last active
July 27, 2018 18:23
-
-
Save pfgray/51c4915effba9b4ed53f36943f01d669 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * ADT | |
| */ | |
| sealed trait MultipleOrOne[A] { | |
| def exists(f: A => Boolean) = | |
| this match { | |
| case Multiple(all) => all.exists(f) | |
| case One(one) => f(one) | |
| } | |
| } | |
| case class Multiple[A](value: Seq[A]) extends MultipleOrOne[A] | |
| case class One[A](value: A) extends MultipleOrOne[A] | |
| /** | |
| * Deserializer | |
| */ | |
| import com.fasterxml.jackson.core.{JsonToken, JsonParser} | |
| import com.fasterxml.jackson.databind.`type`.CollectionType | |
| import com.fasterxml.jackson.databind.deser.{ContextualDeserializer, Deserializers} | |
| import com.fasterxml.jackson.databind.deser.std.StdDeserializer | |
| import com.fasterxml.jackson.databind._ | |
| private class MultipleOrOneDeserializer(valueType: JavaType) | |
| extends StdDeserializer[MultipleOrOne[Any]](classOf[MultipleOrOne[Any]]) | |
| with ContextualDeserializer { | |
| override def createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer[_] = { | |
| val wrapperType = property.getType() | |
| val containedType = wrapperType.containedType(0) | |
| val deserializer = new MultipleOrOneDeserializer(containedType) | |
| return deserializer | |
| } | |
| override def deserialize(jp: JsonParser, ctxt: DeserializationContext): MultipleOrOne[Any] = | |
| jp.getCurrentToken match { | |
| case JsonToken.VALUE_NULL => null | |
| case JsonToken.START_ARRAY => | |
| //deserialize as seq w/ type | |
| Multiple(getSeqDeserializer(valueType, ctxt).deserialize(jp, ctxt).asInstanceOf[Seq[Any]]) | |
| case _ => | |
| //deserialize a type | |
| One(ctxt.findRootValueDeserializer(valueType).deserialize(jp, ctxt).asInstanceOf[Any]) | |
| } | |
| def getSeqDeserializer(entityType: JavaType, ctxt: DeserializationContext) = { | |
| val seqType = CollectionType.construct(classOf[Seq[_]], entityType) | |
| ctxt.findRootValueDeserializer(seqType) | |
| } | |
| } | |
| private object MultipleOrOneDeserializerResolver extends Deserializers.Base { | |
| private val MULT_OR_ONE = classOf[MultipleOrOne[Any]] | |
| override def findBeanDeserializer(javaType: JavaType, config: DeserializationConfig, beanDesc: BeanDescription) = { | |
| val rawClass = javaType.getRawClass | |
| if (!MULT_OR_ONE.isAssignableFrom(rawClass)) null | |
| else new MultipleOrOneDeserializer(javaType) | |
| } | |
| } | |
| /** | |
| * Serializer | |
| */ | |
| import com.fasterxml.jackson.core.JsonGenerator | |
| import com.fasterxml.jackson.databind._ | |
| import com.fasterxml.jackson.databind.ser.Serializers | |
| import com.fasterxml.jackson.databind.ser.std.StdSerializer | |
| /** | |
| * Serializes json into instances of [[MultipleOrOne]]. | |
| */ | |
| private class MultipleOrOneSerializer extends StdSerializer[MultipleOrOne[Any]](classOf[MultipleOrOne[Any]]) { | |
| override def handledType: Class[MultipleOrOne[Any]] = { | |
| return classOf[MultipleOrOne[Any]] | |
| } | |
| override def serialize(input: MultipleOrOne[Any], jgen: JsonGenerator, provider: SerializerProvider): Unit = { | |
| val unwrapped: Any = input match { | |
| case Multiple(list) => list | |
| case One(one) => one | |
| } | |
| provider.defaultSerializeValue(unwrapped, jgen) | |
| } | |
| } | |
| private object MultipleOrOneSerializerResolver extends Serializers.Base { | |
| private val MULT_OR_ONE = classOf[MultipleOrOne[_]] | |
| override def findSerializer(config: SerializationConfig, javaType: JavaType, beanDesc: BeanDescription): JsonSerializer[_] ={ | |
| val rawClass = javaType.getRawClass | |
| if (!MULT_OR_ONE.isAssignableFrom(rawClass)) null | |
| else new MultipleOrOneSerializer() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment