This is an implementation of JSON pointer(RFC 6901) in Scala which extends
JSON pointer syntax(add another three keywords :
,
*
).
This library support 2 ways to access JSON notation data. String path parser
and Scala DSL
Here is a list of supported operators :
Operator | Description | Example |
---|---|---|
/ |
path split | /foo |
: |
array slice(python like) | /-1:-3 (last 3 elements) |
, |
collection of names or indices | /foo,bar or /foo/1,-1,2 |
* |
wildcard | /store/book/* |
Code example:
val json =
"""
|[
| [
| true,
| false,
| null
| ],
| {
| "abc": 1.233e-10,
| "bcd": true,
| "b": null
| },
| {
| "": 1.233e-10,
| "bcd": true,
| "b": 1.23
| },
| false,
| null
|]
""".stripMargin
val value6 = JSONPointer().read[List[Any]]("/*/*", json, List(None, Some((e: String) => e.contains("b"))))
assert(value6 === Some(List(List(1.233E-10, true, null), List(true, 1.23))))
val value7 = JSONPointer().read[Any]("/-3/1", json)
assert(value7 === None)
Code example:
val json =
"""
|[
| [
| true,
| false,
| null
| ],
| {
| "abc": 1.233e-10,
| "bcd": true,
| "b": null
| },
| {
| "": 1.233e-10,
| "bcd": true,
| "b": 1.23
| },
| false,
| null
|]
""".stripMargin
val value0 = JSONPointer().read[List[Any]](new Path / -3 /("bcd", ""), json)
assert(value0 === Some(List(true, 1.233E-10)))
val value1 = JSONPointer().read[List[Any]](new Path / * /(*, (e: String) => e.contains("b")), json)
assert(value1 === Some(List(List(1.233E-10, true, null), List(true, 1.23))))
val value2 = JSONPointer().read[Any](new Path / (1 -> -1) /(*, (_: String) == "b"), json)
assert(value2 === Some(List(null, 1.23)))
val value3 = JSONPointer().read[Boolean](new Path / -3 /"bcd", json)
assert(value3 === Some(true))
val value4 = JSONPointer().read[List[Any]](new Path /(*, _ < _ -1), json)
assert(value4 === Some(List(JSONArray(List(true, false, null)), JSONObject(Map("abc" -> 1.233E-10, "bcd" -> true, "b" -> null)),JSONObject(Map( ""-> 1.233E-10, "bcd" -> true, "b" -> 1.23)), false)))
Character | Escape | Example |
---|---|---|
~ |
~0 (RFC6901 compatibility) |
/~ =>/~0 |
/ |
~1 (RFC6901 compatibility) |
/a/b => /a~1b |
, |
~, |
/foo,bar =>/foo~,bar |
* |
~* |
/store/* =>/store/~* |
You can use these rule to escape character manual.or you can use helper method quote
to do these things.
For example:
import Path._
val path = s"/*/${quote("*")}/${quote("abc,bcd")}"
The path
will compile to string /*/~*/abc~,bcd
When you are using Scala DSL
.you don't need escape any character.
For example:
val path = new Path / * / "*" / "abc,bcd"
The path
will compile to string /*/~*/abc~,bcd
Filters can only used on *
.as you can see above.
We provided three filters.two of them used on JSONArray
.another one used on JSONObject
JSONArray
: Int=>Boolean
and (Int,Int)=>Boolean
JSONObject
: String=>Boolean
Int=>Boolean
:Int
represents JSONArray
index.if result is true
this index of JSONArray
will return.
(Int,Int)=>Boolean
: first Int
represents JSONArray
index.and second Int
represents JSONArray
size.
String=>Boolean
: String
represents JSONObject
key.
JSONPointer().read[List[Any]]("/*/*", json, List(None, Some((e: String) => e.contains("b"))))
You MUST add two filters to the path above.because this path contains two *
.
First filter is None
.represents filter all things.
Second filter is Some((e: String) => e.contains("b"))
.represents filter that key
contains string "b"
.
new Path / * /(*, (e: String) => e.contains("b"))
You don't need add a filter on first *
.because with default filter is None
.
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
/store/book/0/author
=>"Nigel Rees"
/store/book/0,2/author
=>List("Nigel Rees","Herman Melville")
/store/book/0:2/author
=>List("Nigel Rees","Evelyn Waugh","Herman Melville")
/store/book/:2/author
=>List("Nigel Rees","Evelyn Waugh","Herman Melville")
/store/book/-1:-3/author
=>List("J. R. R. Tolkien","Herman Melville","Evelyn Waugh")
/store/book/:-3/author
=>List("Nigel Rees","Evelyn Waugh")
/store/book/:/author
=>List("Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien")
/store/book/0:-1/author
=>List("Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien")
/store/book/*/author
=>List("Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien")
/store/bicycle/color
=>"red"
{
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8,
"0,2":9,
"0:2":10,
"*":11
}
RFC6901 | value(s) |
---|---|
/foo |
["bar", "baz"] |
/foo/0 |
"bar" |
/ |
0 |
/a~1b |
1 |
/c%d |
2 |
/e^f |
3 |
`/g | h` |
/i\\j |
5 |
/k\"l |
6 |
/ |
7 |
/m~0n |
8 |
/0~,2 |
9 |
/0:2 |
10 |
/~* |
11 |