Skip to content

Commit c266e6e

Browse files
committed
Refactor reader API: rename requiredKeyError to requiredFieldError, add overloaded requiredFieldError with already resolved name, replace scanToKey by skipToKey
1 parent dc0e790 commit c266e6e

File tree

4 files changed

+32
-31
lines changed

4 files changed

+32
-31
lines changed

core/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ final class JsonReader private[jsoniter_scala](
5555
private[this] var in: InputStream = null,
5656
private[this] var totalRead: Long = 0,
5757
private[this] var config: ReaderConfig = null) {
58-
def requiredKeyError(reqFields: Array[String], reqBits: Array[Int]): Nothing = {
58+
def requiredFieldError(reqField: String): Nothing = {
59+
var i = appendString("missing required field \"", 0)
60+
i = appendString(reqField, i)
61+
i = appendChar('"', i)
62+
decodeError(i, head - 1, null)
63+
}
64+
65+
def requiredFieldError(reqFields: Array[String], reqBits: Array[Int]): Nothing = {
5966
val len = Math.min(reqFields.length, reqBits.length << 5)
6067
var i = 0
6168
var j = 0
@@ -103,10 +110,9 @@ final class JsonReader private[jsoniter_scala](
103110
def setMark(): Unit = mark = head
104111

105112
@tailrec
106-
def scanToKey(s: String): Unit = if (!isCharBufEqualsTo(readKeyAsCharBuf(), s)) {
113+
def skipToKey(key: String): Boolean = isCharBufEqualsTo(readKeyAsCharBuf(), key) || {
107114
skip()
108-
if (isNextToken(',', head)) scanToKey(s)
109-
else reqFieldError(s)
115+
isNextToken(',', head) && skipToKey(key)
110116
}
111117

112118
def rollbackToMark(): Unit = {
@@ -639,13 +645,6 @@ final class JsonReader private[jsoniter_scala](
639645
decodeError(i, pos, null)
640646
}
641647

642-
private def reqFieldError(s: String): Nothing = {
643-
var i = appendString("missing required field \"", 0)
644-
i = appendString(s, i)
645-
i = appendChar('"', i)
646-
decodeError(i, head - 1, null)
647-
}
648-
649648
private def decodeError(msg: String, pos: Int, cause: Throwable = null): Nothing =
650649
decodeError(appendString(msg, 0), pos, cause)
651650

core/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReaderSpec.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,34 +1951,34 @@ class JsonReaderSpec extends WordSpec with Matchers with PropertyChecks {
19511951
.getMessage.contains("expected preceding call of 'setMark()'"))
19521952
}
19531953
}
1954-
"JsonReader.scanToKey" should {
1955-
"find key-value pair by provided key and set current position of parsing to its value" in {
1954+
"JsonReader.skipToKey" should {
1955+
"return true in case of key is found and set current position of parsing to its value" in {
19561956
val jsonReader = reader("""{"key1":1,"key2":2}""".getBytes)
19571957
jsonReader.isNextToken('{') // enter to JSON object
1958-
jsonReader.scanToKey("key2")
1958+
jsonReader.skipToKey("key2") shouldBe true
19591959
jsonReader.readInt() shouldBe 2
19601960
}
1961-
"throw parsing exception in case of key-value pair of provided key cannot be found" in {
1961+
"return false in case of key cannot be found and set current positing to the closing of object" in {
19621962
val jsonReader = reader("""{"key1":1}""".getBytes)
19631963
jsonReader.isNextToken('{') // enter to JSON object
1964-
assert(intercept[JsonParseException](jsonReader.scanToKey("key2"))
1965-
.getMessage.contains("missing required field \"key2\", offset: 0x00000009"))
1964+
jsonReader.skipToKey("key2")
1965+
jsonReader.isCurrentToken('}') shouldBe true
19661966
}
19671967
}
1968-
"JsonReader.requiredKeyError" should {
1968+
"JsonReader.requiredFieldError" should {
19691969
val jsonReader = reader("{}".getBytes)
19701970
jsonReader.nextToken()
19711971
"throw parsing exception with list of missing required fields that specified by bits" in {
19721972
def check(bits: Int, error: String): Unit =
1973-
assert(intercept[JsonParseException](jsonReader.requiredKeyError(Array("name", "device"), Array(bits)))
1973+
assert(intercept[JsonParseException](jsonReader.requiredFieldError(Array("name", "device"), Array(bits)))
19741974
.getMessage.contains(error))
19751975

19761976
check(3, "missing required field(s) \"name\", \"device\", offset: 0x00000000")
19771977
check(2, "missing required field(s) \"device\", offset: 0x00000000")
19781978
check(1, "missing required field(s) \"name\", offset: 0x00000000")
19791979
}
19801980
"throw illegal argument exception in case of missing required fields cannot be selected" in {
1981-
assert(intercept[IllegalArgumentException](jsonReader.requiredKeyError(Array("name", "device"), Array(0)))
1981+
assert(intercept[IllegalArgumentException](jsonReader.requiredFieldError(Array("name", "device"), Array(0)))
19821982
.getMessage.contains("missing required field(s) cannot be reported for arguments: " +
19831983
"reqFields = Array(name, device), reqBits = Array(0)"))
19841984
}

core/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/core/UserAPI.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ object UserAPI {
5050
if (!in.isCurrentToken('}')) in.objectEndOrCommaError()
5151
}
5252
if (req0 == 0) new Device(id = _id, model = _model)
53-
else in.requiredKeyError(r1, Array(req0))
53+
else in.requiredFieldError(r1, Array(req0))
5454
} else in.readNullOrTokenError(default, '{')
5555

5656
private def d1(in: JsonReader, default: Seq[Device]): Seq[Device] =
@@ -90,7 +90,7 @@ object UserAPI {
9090
if (in.isCurrentToken('}').`unary_!`) in.objectEndOrCommaError()
9191
}
9292
if (req0 == 0) new User(name = _name, devices = _devices)
93-
else in.requiredKeyError(r0, Array(req0))
93+
else in.requiredFieldError(r0, Array(req0))
9494
} else in.readNullOrTokenError(default, '{')
9595

9696
private def e2(x: Device, out: JsonWriter): Unit = {

macros/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ object JsonCodecMaker {
647647
required.map(r => getMappedName(annotations, r))
648648
}
649649
q"""if ($checkReqVars) $construct
650-
else in.requiredKeyError($reqFieldNames, Array(..$reqVarNames))"""
650+
else in.requiredFieldError($reqFieldNames, Array(..$reqVarNames))"""
651651
}
652652
val defaults = getDefaults(tpe)
653653
val readVars = members.map { m =>
@@ -692,8 +692,9 @@ object JsonCodecMaker {
692692
}
693693

694694
val leafClasses = adtLeafClasses(tpe).toSeq
695-
checkDiscriminatorValueCollisions(codecConfig.discriminatorFieldName, leafClasses.map(discriminatorValue))
696-
val discriminatorValueError = q"in.discriminatorValueError(${codecConfig.discriminatorFieldName})"
695+
val discrName = codecConfig.discriminatorFieldName
696+
checkDiscriminatorValueCollisions(discrName, leafClasses.map(discriminatorValue))
697+
val discriminatorValueError = q"in.discriminatorValueError($discrName)"
697698
val readSubclasses = groupByOrdered(leafClasses)(hashCode).map { case (hashCode, subTpes) =>
698699
val checkNameAndReadValue = subTpes.foldRight(discriminatorValueError) { case (subTpe, acc) =>
699700
q"""if (in.isCharBufEqualsTo(l, ${discriminatorValue(subTpe)})) {
@@ -705,12 +706,13 @@ object JsonCodecMaker {
705706
}(breakOut)
706707
q"""in.setMark()
707708
if (in.isNextToken('{')) {
708-
in.scanToKey(${codecConfig.discriminatorFieldName})
709-
val l = in.readStringAsCharBuf()
710-
(in.charBufToHashCode(l): @switch) match {
711-
case ..$readSubclasses
712-
case _ => $discriminatorValueError
713-
}
709+
if (in.skipToKey($discrName)) {
710+
val l = in.readStringAsCharBuf()
711+
(in.charBufToHashCode(l): @switch) match {
712+
case ..$readSubclasses
713+
case _ => $discriminatorValueError
714+
}
715+
} else in.requiredFieldError($discrName)
714716
} else in.readNullOrTokenError(default, '{')"""
715717
} else cannotFindCodecError(tpe)
716718
}

0 commit comments

Comments
 (0)