Created
December 18, 2012 15:22
-
-
Save holograph/4328894 to your computer and use it in GitHub Desktop.
A workaround for the Lift-JSON bug documented here: https://github.com/lift/framework/issues/1080 Basically works by providing a single serializer for multiple enumerations, the order of which determines behavior in case of value collisions. Forked from a gist I accidentally created anonymously.
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
package com.tomergabel.examples | |
import net.liftweb.json._ | |
import net.liftweb.json.JsonDSL._ | |
/** | |
* A chained object which provides JSON serialization/deserialization facilities for multiple enumerations. | |
* Intended as a workaround for the following issue: https://github.com/lift/framework/issues/1080 | |
* | |
* To use simply add to your formats: `implicit val formats = DefaultFormats + new ChainedEnumSerializer( enum1, enum2 )` | |
* | |
* See ChainedEnumSerializerTests for additional usage examples. | |
*/ | |
class ChainedEnumSerializer( enums: Enumeration* ) extends Serializer[ Enumeration#Value ] { | |
private val predicate = classOf[ Enumeration#Value ] | |
private def throwOn( value: JValue ) = | |
throw new MappingException( "Can't convert %s to any of (%s)".format( value, enums.mkString( ", " ) ) ) | |
def deserialize( implicit format: Formats ): PartialFunction[ ( TypeInfo, JValue ), Enumeration#Value ] = { | |
case ( TypeInfo( `predicate`, _ ), json ) => json match { | |
case wrapped @ JString( value ) => | |
enums.flatMap { _.values.find( _.toString == value ) }.headOption getOrElse throwOn( wrapped ) | |
case value => throwOn( value ) | |
} | |
} | |
def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { | |
case i: Enumeration#Value => i.toString | |
} | |
} |
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
package com.tomergabel.examples | |
import org.scalatest.matchers.ShouldMatchers | |
import org.scalatest.FlatSpec | |
/** | |
* Created by tomer on 12/18/12. | |
*/ | |
class ChainedEnumSerializerTests extends FlatSpec with ShouldMatchers { | |
import ChainedEnumSerializerTests._ | |
import net.liftweb.json._ | |
implicit val formats = DefaultFormats + new ChainedEnumSerializer( Enum1, Enum2 ) | |
"ChainedEnumSerializer" should "return correct enumeration value from the first enumeration" in { | |
val json = parse( """{"key1":"value1"}""" ) | |
val result = json.extract[ TestObject ] | |
result should be === TestObject( key1 = Some( Enum1.value1 ) ) | |
} | |
it should "correctly fall back to a secondary enumeraiton if a value does not match the first enumeration" in { | |
val json = parse( """{"key2":"value2"}""" ) | |
val result = json.extract[ TestObject ] | |
result should be === TestObject( key2 = Some( Enum2.value2 ) ) | |
} | |
it should "select a value from the first enumeration in case of collision between enumeration values" in { | |
val json = parse( """{"key1":"collision"}""" ) | |
val result = json.extract[ TestObject ] | |
result should be === TestObject( key1 = Some( Enum1.collision ) ) | |
} | |
it should "throw a MappingException in case of an invalid value accross all enumerations" in { | |
val json = parse( """{"m":"invalid"}""" ) | |
evaluating { json.extract[ TestObject2 ] } should produce[ MappingException ] | |
} | |
} | |
private object ChainedEnumSerializerTests { | |
object Enum1 extends Enumeration { val value1, collision = Value } | |
object Enum2 extends Enumeration { val value2, collision = Value } | |
case class TestObject( key1: Option[ Enum1.Value ] = None, key2: Option[ Enum2.Value ] = None ) | |
case class TestObject2( m: Enum1.Value ) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment