Skip to content

Commit

Permalink
Add Path type
Browse files Browse the repository at this point in the history
  • Loading branch information
garyb committed Oct 18, 2023
1 parent c6b78b8 commit 7d0ea1d
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
39 changes: 39 additions & 0 deletions src/JSON/Path.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module JSON.Path where

import Prelude

import Data.Maybe (Maybe(..))
import JSON (JSON)
import JSON as JSON
import JSON.Array as JArray
import JSON.Object as JObject

data Path
= Top
| AtKey String Path
| AtIndex Int Path

derive instance Eq Path
derive instance Ord Path

instance Show Path where
show = case _ of
Top -> "Top"
AtKey key rest -> "(AtKey " <> show key <> " " <> show rest <> ")"
AtIndex ix rest -> "(AtIndex " <> show ix <> " " <> show rest <> ")"

get :: Path -> JSON -> Maybe JSON
get path json =
case path of
Top -> Just json
AtKey key rest -> JObject.lookup key =<< JSON.toJObject =<< get rest json
AtIndex ix rest -> JArray.index ix =<< JSON.toJArray =<< get rest json

print :: Path -> String
print path = "$" <> go path ""
where
go :: Path -> String -> String
go p acc = case p of
Top -> acc
AtKey k rest -> go rest ("." <> k <> acc)
AtIndex ix rest -> go rest ("[" <> show ix <> "]" <> acc)
20 changes: 19 additions & 1 deletion test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Effect.Console (log)
import JSON as J
import JSON.Array as JA
import JSON.Object as JO
import Test.Assert (assertTrue)
import JSON.Path as Path
import Test.Assert (assertEqual, assertTrue)

main :: Effect Unit
main = do
Expand Down Expand Up @@ -43,3 +44,20 @@ main = do

log "Check array concat"
assertTrue $ JA.fromArray (J.fromInt <$> [ 1, 2 ]) <> JA.fromArray (J.fromInt <$> [ 2, 3 ]) == JA.fromArray (J.fromInt <$> [ 1, 2, 2, 3 ])

log "Check path printing"
assertEqual
{ expected: "$.data[0].field"
, actual: Path.print (Path.AtKey "field" (Path.AtIndex 0 (Path.AtKey "data" Path.Top)))
}

log "Check path get"
assertTrue $ Path.get Path.Top (J.fromString "hello") == Just (J.fromString "hello")
assertTrue $ Path.get Path.Top (J.fromJArray (JA.fromArray [ J.fromInt 42 ])) == Just (J.fromJArray (JA.fromArray [ J.fromInt 42 ]))
assertTrue $ Path.get (Path.AtIndex 0 Path.Top) (J.fromJArray (JA.fromArray [ J.fromInt 42, J.fromString "X", J.fromBoolean true ])) == Just (J.fromInt 42)
assertTrue $ Path.get (Path.AtIndex 1 Path.Top) (J.fromJArray (JA.fromArray [ J.fromInt 42, J.fromString "X", J.fromBoolean true ])) == Just (J.fromString "X")
assertTrue $ Path.get (Path.AtIndex 5 Path.Top) (J.fromJArray (JA.fromArray [ J.fromInt 42, J.fromString "X", J.fromBoolean true ])) == Nothing
assertTrue $ Path.get (Path.AtKey "a" Path.Top) (J.fromJObject (JO.fromEntries [ Tuple "a" (J.fromInt 1), Tuple "x" (J.fromBoolean false) ])) == Just (J.fromInt 1)
assertTrue $ Path.get (Path.AtKey "x" Path.Top) (J.fromJObject (JO.fromEntries [ Tuple "a" (J.fromInt 1), Tuple "x" (J.fromBoolean false) ])) == Just (J.fromBoolean false)
assertTrue $ Path.get (Path.AtKey "z" Path.Top) (J.fromJObject (JO.fromEntries [ Tuple "a" (J.fromInt 1), Tuple "x" (J.fromBoolean false) ])) == Nothing
assertTrue $ Path.get (Path.AtKey "x" (Path.AtIndex 1 Path.Top)) (J.fromJArray (JA.fromArray [ J.fromString "skip", (J.fromJObject (JO.fromEntries [ Tuple "a" (J.fromInt 1), Tuple "x" (J.fromBoolean false) ])) ])) == Just (J.fromBoolean false)

0 comments on commit 7d0ea1d

Please sign in to comment.