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 |