Skip to content

Commit 7d0ea1d

Browse files
committed
Add Path type
1 parent c6b78b8 commit 7d0ea1d

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/JSON/Path.purs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module JSON.Path where
2+
3+
import Prelude
4+
5+
import Data.Maybe (Maybe(..))
6+
import JSON (JSON)
7+
import JSON as JSON
8+
import JSON.Array as JArray
9+
import JSON.Object as JObject
10+
11+
data Path
12+
= Top
13+
| AtKey String Path
14+
| AtIndex Int Path
15+
16+
derive instance Eq Path
17+
derive instance Ord Path
18+
19+
instance Show Path where
20+
show = case _ of
21+
Top -> "Top"
22+
AtKey key rest -> "(AtKey " <> show key <> " " <> show rest <> ")"
23+
AtIndex ix rest -> "(AtIndex " <> show ix <> " " <> show rest <> ")"
24+
25+
get :: Path -> JSON -> Maybe JSON
26+
get path json =
27+
case path of
28+
Top -> Just json
29+
AtKey key rest -> JObject.lookup key =<< JSON.toJObject =<< get rest json
30+
AtIndex ix rest -> JArray.index ix =<< JSON.toJArray =<< get rest json
31+
32+
print :: Path -> String
33+
print path = "$" <> go path ""
34+
where
35+
go :: Path -> String -> String
36+
go p acc = case p of
37+
Top -> acc
38+
AtKey k rest -> go rest ("." <> k <> acc)
39+
AtIndex ix rest -> go rest ("[" <> show ix <> "]" <> acc)

test/Main.purs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import Effect.Console (log)
99
import JSON as J
1010
import JSON.Array as JA
1111
import JSON.Object as JO
12-
import Test.Assert (assertTrue)
12+
import JSON.Path as Path
13+
import Test.Assert (assertEqual, assertTrue)
1314

1415
main :: Effect Unit
1516
main = do
@@ -43,3 +44,20 @@ main = do
4344

4445
log "Check array concat"
4546
assertTrue $ JA.fromArray (J.fromInt <$> [ 1, 2 ]) <> JA.fromArray (J.fromInt <$> [ 2, 3 ]) == JA.fromArray (J.fromInt <$> [ 1, 2, 2, 3 ])
47+
48+
log "Check path printing"
49+
assertEqual
50+
{ expected: "$.data[0].field"
51+
, actual: Path.print (Path.AtKey "field" (Path.AtIndex 0 (Path.AtKey "data" Path.Top)))
52+
}
53+
54+
log "Check path get"
55+
assertTrue $ Path.get Path.Top (J.fromString "hello") == Just (J.fromString "hello")
56+
assertTrue $ Path.get Path.Top (J.fromJArray (JA.fromArray [ J.fromInt 42 ])) == Just (J.fromJArray (JA.fromArray [ J.fromInt 42 ]))
57+
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)
58+
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")
59+
assertTrue $ Path.get (Path.AtIndex 5 Path.Top) (J.fromJArray (JA.fromArray [ J.fromInt 42, J.fromString "X", J.fromBoolean true ])) == Nothing
60+
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)
61+
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)
62+
assertTrue $ Path.get (Path.AtKey "z" Path.Top) (J.fromJObject (JO.fromEntries [ Tuple "a" (J.fromInt 1), Tuple "x" (J.fromBoolean false) ])) == Nothing
63+
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 commit comments

Comments
 (0)