Skip to content

Commit 16e2211

Browse files
authored
Add feed(InputStream) overload that defaults to 8 KiB buffer. (#5)
Add examples to readme.
1 parent 1dde729 commit 16e2211

File tree

3 files changed

+113
-15
lines changed

3 files changed

+113
-15
lines changed

README.md

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,102 @@
11
# json-skiff
22

3-
A streaming [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) evaluator.
3+
A streaming [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) evaluator in Java.
44

55
1. Give it a list of JSON pointers and callbacks.
66
2. Feed it JSON.
77
3. Get notified when the target elements are seen.
88

99
Less capable, but simpler and faster than the excellent [JsonSurfer](https://github.com/wanglingsong/JsonSurfer) library.
1010

11-
## Usage
11+
## Maven coordinates
1212

13-
### Selecting array elements
13+
```xml
14+
<dependency>
15+
<groupId>com.couchbase</groupId>
16+
<artifactId>json-skiff</artifactId>
17+
<version>1.0.0</version>
18+
</dependency>
19+
```
1420

15-
Normally, a `-` in a JSON Pointer refers to the last element of an array.
16-
`json-skiff` bends the rules a bit, and interprets `-` as matching _all_ array elements.
1721

18-
Consider this JSON document:
22+
## Usage
23+
24+
Imagine you want to parse this very nice JSON document.
1925

2026
```json
2127
{
22-
"magicWords": [
23-
"alakazam",
24-
"xyzzy"
25-
]
28+
"name": "Alice",
29+
"friends": [
30+
"White Rabbit",
31+
"Mad Hatter"
32+
]
33+
}
34+
```
35+
36+
Start by building a `JsonStreamParser` and registering callbacks for various JSON pointers.
37+
38+
The argument to a callback is a `MatchedValue`.
39+
In this example we expect the matched values to be JSON Strings, so we use `MatchedValue.readString()` to get the value.
40+
41+
```java
42+
JsonStreamParser parser = JsonStreamParser.builder()
43+
.doOnValue("/friends/-", it -> System.out.println("Friend: " + it.readString()))
44+
.doOnValue("/name", it -> System.out.println("Name: " + it.readString()))
45+
.build();
46+
```
47+
48+
The JSON pointers may be specified in any order -- they don't need to match the order the elements appear in the JSON.
49+
The parser ignores elements that don't match the JSON pointers.
50+
51+
When the very nice JSON document is fed to the parser, you'll see this output:
52+
53+
```text
54+
Name: Alice
55+
Friend: White Rabbit
56+
Friend: Mad Hatter
57+
```
58+
59+
> **NOTE:** It's important to call `parser.close()` (or use a `try-with-resources` statement) when you're done with the parser.
60+
61+
62+
### Feeding from an InputStream
63+
64+
```java
65+
try (InputStream is = createMyJsonInputStream()) {
66+
parser.feed(is);
67+
parser.endOfInput();
68+
}
69+
```
70+
71+
If you want, you can feed the parser from additional input streams before calling `parser.endOfInput()`.
72+
73+
74+
### Feeding from a byte array
75+
76+
You can also feed the parser incrementally.
77+
This contrived example feeds the parser every byte of an array, one byte at a time:
78+
79+
```java
80+
byte[] bytes = getMyJsonByteArray();
81+
82+
for (int offset = 0; offset < bytes.length; offset++) {
83+
int length = 1;
84+
parser.feed(bytes, offset, length);
2685
}
27-
```
28-
A callback associated with `/magicWords/-` is invoked a total of two times: once for `"alakazam"` and once for `"xyzzy"`.
86+
parser.endOfInput();
87+
```
88+
89+
### Feeding from a java.nio.ByteBuffer
90+
91+
There's an overload of `parser.feed()` that takes a ByteBuffer.
92+
93+
94+
### Selecting array elements
95+
96+
Normally, a `-` in a JSON Pointer refers to the non-existent element past the end of an array.
97+
`json-skiff` bends this rule, and interprets `-` as matching _every_ array element.
98+
99+
In the previous example we used `/friends/-` to select every element of the `friends` array.
29100

30101
The `-` does not need to be the last component of the pointer.
31102
Consider this JSON document:
@@ -43,12 +114,32 @@ Consider this JSON document:
43114
}
44115
```
45116

46-
A callback associated with `/widgets/-/serialNumber` is invoked a total of two times: once for `"123"` and once for `"XYZ"`.
117+
A callback for `/widgets/-/serialNumber` is invoked once for `"123"` and once for `"XYZ"`.
118+
119+
120+
### Selecting whole Objects and Arrays
121+
122+
If the target field value is a JSON Array or Object, use `MatchedValue.bytes()` to get the bytes of the Array / Object, and use your favorite JSON processing library to parse it.
123+
124+
This is also the recommended way to handle a value whose type is not known at runtime.
125+
126+
127+
### Nullable values
128+
129+
If you expect a matched value might be null, check for null by calling `MatchedValue.isNull()` before calling any of the `read*` methods to avoid `NullPointerException`.
47130

48131

49132
## FAQ
50133

134+
### How to select only the Nth element of an array?
135+
136+
Sorry, this library does not support JSON pointers that reference specific array elements.
137+
138+
### How to do more complex matching?
139+
140+
If a JSON pointer isn't sufficient, take a look at [JsonSurfer](https://github.com/wanglingsong/JsonSurfer) which lets you use JSON Path to specify complex matching rules.
141+
51142
### Is this library an officially supported Couchbase product?
52143

53144
No.
54-
This library is not covered by any Couchbase support contract.
145+
You are welcome to file issues here on GitHub, but Couchbase Technical Support is not responsible for this library, and it's not covered by any Couchbase support contract.

pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
<version>2.18.3</version>
7878
</dependency>
7979

80-
8180
<dependency>
8281
<groupId>org.junit.jupiter</groupId>
8382
<artifactId>junit-jupiter</artifactId>

src/main/java/com/couchbase/jsonskiff/JsonStreamParser.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ private JsonStreamParser(PathTree pathTree) {
8282
}
8383
}
8484

85+
/**
86+
* @throws UncheckedIOException if malformed JSON is detected in this chunk of input
87+
* @throws RuntimeException if a value consumer throws an exception
88+
*/
89+
public void feed(InputStream is) {
90+
feed(is, 8 * 1024);
91+
}
92+
8593
/**
8694
* @throws UncheckedIOException if malformed JSON is detected in this chunk of input
8795
* @throws RuntimeException if a value consumer throws an exception

0 commit comments

Comments
 (0)