Skip to content

Latest commit

 

History

History
250 lines (210 loc) · 7.53 KB

README.md

File metadata and controls

250 lines (210 loc) · 7.53 KB

jsonpath

Build Status Coverage Status

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

Syntax

String path parser:

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)

Scala DSL:

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)))

Escape

String path parser:

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

Scala DSL:

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

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.

String path parser:

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".

Scala DSL:

new Path / * /(*, (e: String) => e.contains("b"))

You don't need add a filter on first *.because with default filter is None.

Examples

Normal:

{
    "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"

Special:

{
    "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

References