From bc5f85e8595057d7f02c82f8d577c62fea5f52d5 Mon Sep 17 00:00:00 2001 From: Lucas Satabin Date: Thu, 3 Sep 2026 09:10:03 +0200 Subject: [PATCH 1/2] Fix interpretation of integer segment on objects When the pointer segment is an integer and it is evaluated on an object, look for the field name being that integer instead of failing. Fixes #517 --- .scalafmt.conf | 2 +- .../main/scala/diffson/jsonpointer/package.scala | 16 ++++++++-------- .../src/main/scala/diffson/TestJsonPointer.scala | 6 +++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index 262ffbfa..60ce817c 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -14,7 +14,7 @@ rewrite.rules = [ prefercurlyfors ] -runner.dialect = scala213 +runner.dialect = scala213source3 fileOverride { "glob:**/src/*/scala-3/**" { runner.dialect = scala3 diff --git a/core/src/main/scala/diffson/jsonpointer/package.scala b/core/src/main/scala/diffson/jsonpointer/package.scala index f1f54a59..febc7909 100644 --- a/core/src/main/scala/diffson/jsonpointer/package.scala +++ b/core/src/main/scala/diffson/jsonpointer/package.scala @@ -16,13 +16,12 @@ package diffson -import cats._ -import cats.syntax.all._ import cats.data.Chain - -import scala.util.Try +import cats.syntax.all.* +import cats.{MonadError, Show} import scala.collection.compat.immutable.ArraySeq +import scala.util.Try package object jsonpointer { @@ -37,19 +36,20 @@ package object jsonpointer { def evaluate[F[_], Json](json: Json)(implicit F: MonadError[F, Throwable], Json: Jsony[Json]): F[Json] = F.tailRecM((json, Pointer(parts), Pointer.Root)) { - case (JsObject(obj), Inner(Left(elem), tl), parent) => - F.pure(Left((obj.getOrElse(elem, Json.Null), tl, parent / elem))) + case (JsObject(obj), Inner(elem, tl), parent) => + val fieldName = elem.fold(identity, _.toString()) + F.pure(Left((obj.getOrElse(fieldName, Json.Null), tl, parent / fieldName))) case (JsArray(arr), Inner(Right(idx), tl), parent) => if (idx >= arr.size) // we know (by construction) that the index is greater or equal to zero F.raiseError(new PointerException(show"element $idx does not exist at path $parent")) else F.pure(Left((arr(idx), tl, parent / idx))) - case (value, Pointer.Root, _) => - F.pure(Right(value)) case (_, Inner(elem, _), parent) => val elems = elem.fold(identity, _.toString) F.raiseError(new PointerException(show"element $elems does not exist at path $parent")) + case (value, _, _) => + F.pure(Right(value)) } } diff --git a/testkit/shared/src/main/scala/diffson/TestJsonPointer.scala b/testkit/shared/src/main/scala/diffson/TestJsonPointer.scala index 729a28d4..362af565 100644 --- a/testkit/shared/src/main/scala/diffson/TestJsonPointer.scala +++ b/testkit/shared/src/main/scala/diffson/TestJsonPointer.scala @@ -17,7 +17,7 @@ package diffson package jsonpointer -import cats.implicits._ +import cats.syntax.all._ import org.scalatest.flatspec.AnyFlatSpec @@ -100,4 +100,8 @@ abstract class TestJsonPointer[Json](implicit Json: Jsony[Json]) parsePointer("/123456789012") should be(Pointer.Root / "123456789012") } + it should "access the object field if applied to an obkect" in { + parsePointer("/0").evaluate[Try, Json](parseJson("""{"0": "value"}""")).get should be("value": Json) + } + } From cfc5d50398a998b77d6b3d9d9a2ce09b0fc9156f Mon Sep 17 00:00:00 2001 From: Lucas Satabin Date: Sun, 13 Sep 2026 21:12:02 +0200 Subject: [PATCH 2/2] Use `Integer.toString` for clarity --- core/src/main/scala/diffson/jsonpointer/package.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/diffson/jsonpointer/package.scala b/core/src/main/scala/diffson/jsonpointer/package.scala index febc7909..c1760dfa 100644 --- a/core/src/main/scala/diffson/jsonpointer/package.scala +++ b/core/src/main/scala/diffson/jsonpointer/package.scala @@ -37,7 +37,7 @@ package object jsonpointer { def evaluate[F[_], Json](json: Json)(implicit F: MonadError[F, Throwable], Json: Jsony[Json]): F[Json] = F.tailRecM((json, Pointer(parts), Pointer.Root)) { case (JsObject(obj), Inner(elem, tl), parent) => - val fieldName = elem.fold(identity, _.toString()) + val fieldName = elem.fold(identity, Integer.toString(_)) F.pure(Left((obj.getOrElse(fieldName, Json.Null), tl, parent / fieldName))) case (JsArray(arr), Inner(Right(idx), tl), parent) => if (idx >= arr.size)