Copyright | (C) 2016 Ladislav Lhotka |
---|---|
License | BSD3 |
Maintainer | Ladislav Lhotka <lhotka@nic.cz> |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
Zipper interface for JSON Value
.
- data Context
- data Location = Loc Value Context
- anchor :: Value -> Maybe Location
- value :: Location -> Value
- getValue :: Maybe Location -> Value
- replace :: Value -> Location -> Maybe Location
- up :: Location -> Maybe Location
- top :: Location -> Maybe Location
- child :: Text -> Location -> Maybe Location
- sibling :: Text -> Location -> Maybe Location
- addSibling :: Text -> Value -> Location -> Maybe Location
- entry :: Int -> Location -> Maybe Location
- firstEntry :: Location -> Maybe Location
- lastEntry :: Location -> Maybe Location
- next :: Location -> Maybe Location
- previous :: Location -> Maybe Location
- back :: Int -> Location -> Maybe Location
- forward :: Int -> Location -> Maybe Location
- jump :: Int -> Location -> Maybe Location
- addBefore :: Value -> Location -> Maybe Location
- addAfter :: Value -> Location -> Maybe Location
Using the zipper interface
This module implements a zipper interface for JSON Value
s pretty
much along the lines of Gérard Huet's original
paper: it defines the Location
type containing
- a JSON
Value
that is the current focus, and - context representing essentially the rest of the JSON document with a hole in the place of the focused value.
Due to the heterogeneity of JSON data, the API is not as uniform as
for "neat" data structures in that some operations are only
intended to work for certain Location
types. In the following
subsections, the functions are classified according to the context
for which they are designed.
Typically, the motion and editing operations will be executed as
actions in the Maybe
monad. Such an action may fail if
- it is executed in a wrong location, or
- the value being addressed doesn't exist (e.g. executing
previous
if the focus is on the first entry of an array).
Example
Decode a simple JSON document and put it into the top-level zipper context:
>>>
let tloc = decode "{\"root\": {\"foo\": [1,2], \"bar\": true}}" >>= anchor
Move all the way to entry #1 of the foo
array:
>>>
let foo1 = tloc >>= child "root" >>= child "foo" >>= entry 1
The value at this location is number 2:
>>>
getValue foo1
Number 2.0
Add a new entry – number 3 – before that entry, and go back to the top location:
>>>
let tloc' = foo1 >>= addBefore (Number 3) >>= top
Now we can extract and encode the modified JSON document:
>>>
encode $ getValue tloc'
"{\"root\":{\"foo\":[1,3,2],\"bar\":true}}"
Zipper types
Adding and removing context
getValue :: Maybe Location -> Value Source
Return the value that may not be present. Null
represents a
missing value.
Functions for all locations
Functions for object locations
child :: Text -> Location -> Maybe Location Source
When at object location, go to the child member with the specified name.
Functions for object member locations
sibling :: Text -> Location -> Maybe Location Source
When at object member location, go to the sibling member with the specified name.
addSibling :: Text -> Value -> Location -> Maybe Location Source
When at object member location, add a new sibling with the given name
and value, and move the focus to the new sibling. Nothing
is
returned if a sibling of that name already exists.
Functions for array locations
entry :: Int -> Location -> Maybe Location Source
When at array location, go to the entry with the specified position.
firstEntry :: Location -> Maybe Location Source
When at array location, go to the first entry.
Functions for array entry locations
previous :: Location -> Maybe Location Source
When at array entry location, go to the preceding entry.
back :: Int -> Location -> Maybe Location Source
When at array entry location, go to the n-th preceding entry.
forward :: Int -> Location -> Maybe Location Source
When at array entry location, go to the n-th following entry.
jump :: Int -> Location -> Maybe Location Source
When at array entry location, go to the n-th preceding or following entry depending on the sign of the first argument (negative = back).