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 JSONPointerTo 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: EncloseAbstractDictinstances 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 = trueis given to aJSONPointer.Pointerconstructer
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")