From 1f8f1a2f245876e43ad1291fb2c1db7fe516fbd9 Mon Sep 17 00:00:00 2001 From: Neil Sanchala Date: Thu, 23 Feb 2012 20:10:06 -0800 Subject: [PATCH] fix issue with Either deserialization with case classes EitherDeserializer was reusing a JsonParser first when it attempted to parse the Left, then if that failed and it tried to parse the Right. If the Left and Right sides look similar enough that the nextToken method was ever called on the parser, then the parsing of the Right could fail. --- .../jerkson/deser/EitherDeserializer.scala | 8 ++++- .../jerkson/tests/EitherSupportSpec.scala | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/com/codahale/jerkson/tests/EitherSupportSpec.scala diff --git a/src/main/scala/com/codahale/jerkson/deser/EitherDeserializer.scala b/src/main/scala/com/codahale/jerkson/deser/EitherDeserializer.scala index 75ab212..23b2916 100644 --- a/src/main/scala/com/codahale/jerkson/deser/EitherDeserializer.scala +++ b/src/main/scala/com/codahale/jerkson/deser/EitherDeserializer.scala @@ -17,7 +17,13 @@ class EitherDeserializer(config: DeserializationConfig, try { Left(tp.getCodec.readValue[Object](tp, javaType.containedType(0))) } catch { - case _ => Right(tp.getCodec.readValue[Object](tp, javaType.containedType(1))) + case _ => { + // We don't want to reuse the same parser that was used in the + // try-block, as the read there may have used nextToken() and advanced + // us past the point where we expect to be. + val tpRight = new TreeTraversingParser(node, jp.getCodec) + Right(tpRight.getCodec.readValue[Object](tpRight, javaType.containedType(1))) + } } } } diff --git a/src/test/scala/com/codahale/jerkson/tests/EitherSupportSpec.scala b/src/test/scala/com/codahale/jerkson/tests/EitherSupportSpec.scala new file mode 100644 index 0000000..2560504 --- /dev/null +++ b/src/test/scala/com/codahale/jerkson/tests/EitherSupportSpec.scala @@ -0,0 +1,33 @@ +package com.codahale.jerkson.tests + +import com.codahale.jerkson.Json._ +import com.codahale.simplespec.Spec +import com.codahale.jerkson.ParsingException +import org.codehaus.jackson.node.IntNode +import org.junit.Test + +class EitherSupportSpec extends Spec { + class `An Either of two case classes` { + @Test def `is parseable when the Left is used` = { + val e = parse[Either[CaseClassWithArrays, CaseClass]]("""{"one": "a", "two": [ "b", "c" ], "three": [ 0, 1 ]}""") + + e.isLeft.must(be(true)) + + val c = e.left.get + c.one.must(be("a")) + c.two.must(be(Array[String]("b", "c"))) + c.three.must(be(Array[Int](0, 1))) + } + + @Test def `is parseable when the Right is used` = { + val e = parse[Either[CaseClass, CaseClassWithArrays]]("""{"one": "a", "two": [ "b", "c" ], "three": [ 0, 1 ]}""") + + e.isRight.must(be(true)) + + val c = e.right.get + c.one.must(be("a")) + c.two.must(be(Array[String]("b", "c"))) + c.three.must(be(Array[Int](0, 1))) + } + } +}