Skip to content

Commit

Permalink
Better handle String hashCode collisions in JsLookup (#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
htmldoug authored Nov 23, 2021
1 parent 19772a1 commit 533f98a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ package play.api.libs.json

import org.openjdk.jmh.annotations._

/**
* @see https://github.com/playframework/play-json/pull/193
*/
@State(Scope.Benchmark)
class JsonParsing_01_ParseManyFields {
@Param(Array("10", "100", "1000", "10000", "100000"))
var n: Int = 100

var stringToParse: String = _

case class Example(s: String)
object Example {
implicit val reads = Json.reads[Example]
}

@Setup
def setup(): Unit = {
val value = "42"
Expand All @@ -21,7 +29,22 @@ class JsonParsing_01_ParseManyFields {
}

@Benchmark
def parseObject(): Unit = {
def parseObject(): JsValue = {
Json.parse(stringToParse)
}

@Benchmark
def parseObjectAs(): Example = {
Json.parse(stringToParse).as[Example]
}

@Benchmark
def parseObjectLookup(): JsValue = {
(Json.parse(stringToParse) \ "s").as[JsString]
}

@Benchmark
def parseObjectValue(): Option[JsValue] = {
Json.parse(stringToParse).as[JsObject].value.get("s")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ case class JsLookup(result: JsLookupResult) extends AnyVal {
case JsDefined(x) =>
x match {
case arr: JsObject =>
arr.value.get(fieldName) match {
arr.underlying.get(fieldName) match {
case Some(x) => x
case None => throw new NoSuchElementException(String.valueOf(fieldName))
}
Expand Down Expand Up @@ -101,7 +101,7 @@ case class JsLookup(result: JsLookupResult) extends AnyVal {
*/
def \(fieldName: String): JsLookupResult = result match {
case JsDefined(obj @ JsObject(_)) =>
obj.value
obj.underlying
.get(fieldName)
.map(JsDefined.apply)
.getOrElse(JsUndefined(s"'$fieldName' is undefined on object: $obj"))
Expand All @@ -117,7 +117,7 @@ case class JsLookup(result: JsLookupResult) extends AnyVal {
*/
def \\(fieldName: String): collection.Seq[JsValue] = result match {
case JsDefined(obj: JsObject) =>
obj.value.foldLeft(Seq[JsValue]())((o, pair) =>
obj.underlying.foldLeft(Seq[JsValue]())((o, pair) =>
pair match {
case (key, value) if key == fieldName => o ++ (value +: (value \\ fieldName))
case (_, value) => o ++ (value \\ fieldName)
Expand Down

0 comments on commit 533f98a

Please sign in to comment.