Implementation of JSON Pointers according to RFC 6901
JSONPointer is a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a '/' (%x2F) character.
- JSONPointer Syntax Support: The package supports the creation and manipulation of JSON Pointers, allowing users to navigate and access elements within JSON data structures.
Exported Functions and Types:
@j_str
: allowing string literalj"/foo"
to construct a JSONPointerPointerDict
: A type that extends AbstractDict to support JSON Pointers.has_pointer
,get_pointer
,set_pointer!
: Functions to check if a pointer exists, retrieve a value by pointer, and set a value by pointer, respectively.
JSONPointer is a registered package, you can simply install it by using the Julia package manager in two ways:
with the Pkg
module
using Pkg
Pkg.add("JSONPointer")
or the package manager REPL, simply press the ']' key.
pkg> add JSONPointer
To create a JSONPointer, you can use the litteral string j
or more verbose JSONPointer.Pointer
type
using JSONPointer
p1 = j"/foo/bar"
p2 = j"/bar/1"
# or
p1 = JSONPointer.Pointer("/foo/bar")
p2 = JSONPointer.Pointer("/bar/1")
In this example, p1 and p2 are JSONPointers that reference paths within a JSON structure.
To integrate JSONPointer with AbstractDict types in Julia, you have two effective approaches:
-
Leveraging JSONPointer Functions: Utilize the newly defined functions specifically for JSONPointer, such as
set_pointer!
,get_pointer
, andhas_pointer
, to interact with your AbstractDict objects. -
Employing
PointerDict
: EncloseAbstractDict
instances within PointerDict, which seamlessly integrates with the base interface, enabling operations such asdoc[key]
,doc[key] = value
, andhaskey(doc, key)
.
p1 = j"/foo/bar"
p2 = j"/bar/1"
doc = Dict{String, Any}()
set_pointer!(doc, p1, 1)
set_pointer!(doc, p2, 2)
# with PointerDict
pointer_doc = PointerDict(p1 => 1, p2 =>2)
Continuing from the previous example
pointer_doc[j"/foo"] == get_pointer(doc, j"/foo")
pointer_doc[j"/bar"][1] == get_pointer(doc, j"/bar/1")
One other essential features is checking if key
is valid within Abstractdict
doc = Dict("a" => Dict("b" => Dict("c" => [100, Dict("d" => 200)])))
has_pointer(doc, j"/a")
has_pointer(doc, j"/a/b")
has_pointer(doc, j"/a/b/c/1")
has_pointer(doc, j"/a/b/c/2")
has_pointer(doc, j"/a/b/c/2/d")
pointer_doc = PointerDict(doc)
haskey(pointer_doc, j"/a")
haskey(pointer_doc, j"/a/b")
haskey(pointer_doc, j"/a/b/c/1")
haskey(pointer_doc, j"/a/b/c/2")
haskey(pointer_doc, j"/a/b/c/2/d")
- Note that Julia is using 1-based index, 0-based index can be used if argument
shift_index = true
is given to aJSONPointer.Pointer
constructer
julia>JSONPointer.Pointer(j"/foo/0"; shift_index = true)
You can enforce type with ::T
at the end of pointer:
p1 = j"/a::array"
p2 = j"/b/2::string"
data = PointerDict(p1 => [1,2,3], p2 => "Must be a String")
# both of these will throw errors
data = PointerDict(p1 => "MethodError", p2 => "Must be a String")
data = PointerDict(p1 => [1,2,3], p2 => :MethodError)
The type T
must be one of the six types supported by JSON:
::string
::number
::object
::array
::boolean
::null
JSONPointer provides basic manipulations after the creation
p1 = j"/Root/header"
append!(p1, "id") == j"/Root/header/id"
deleteat!(p1, 1) == j"/header/id"
pop!(p1) == j"/header"
Note that these mutates the pointer
If you need to use a string number as key for dict, put '' in front of a number
p1 = j"/\10"
data = PointerDict(p1 => "this won't be a array")