0
# Dynamic JSON Navigation
1
2
JSONNavi provides a jQuery-like API for dynamically traversing and manipulating JSON structures without requiring predefined types. It's particularly useful for working with unknown or complex JSON schemas.
3
4
## Overview
5
6
JSONNavi allows you to:
7
- Navigate JSON structures using path-like syntax
8
- Create and modify JSON data dynamically
9
- Access values with automatic type conversion
10
- Handle navigation errors gracefully
11
- Work with both objects and arrays seamlessly
12
13
## Factory Methods
14
15
```java { .api }
16
public static JSONNavi<JSONAwareEx> newInstance();
17
public static JSONNavi<JSONObject> newInstanceObject();
18
public static JSONNavi<JSONArray> newInstanceArray();
19
```
20
21
Create new JSONNavi instances for different root types.
22
23
```java
24
// Generic navigator (can hold any JSON type)
25
JSONNavi<JSONAwareEx> nav = JSONNavi.newInstance();
26
27
// Object-specific navigator
28
JSONNavi<JSONObject> objNav = JSONNavi.newInstanceObject();
29
30
// Array-specific navigator
31
JSONNavi<JSONArray> arrNav = JSONNavi.newInstanceArray();
32
```
33
34
## Constructors
35
36
```java { .api }
37
public JSONNavi(JsonReaderI<? super T> mapper);
38
public JSONNavi(String json);
39
public JSONNavi(String json, JsonReaderI<T> mapper);
40
public JSONNavi(String json, Class<T> mapTo);
41
```
42
43
Create navigators from JSON strings with optional custom parsing.
44
45
```java
46
// Parse JSON string and navigate
47
JSONNavi<?> nav = new JSONNavi<>("{\"user\": {\"name\": \"John\", \"age\": 30}}");
48
49
// Parse with custom mapper
50
JSONNavi<MyUser> userNav = new JSONNavi<>(jsonString, MyUser.class);
51
52
// Parse with custom reader
53
JSONNavi<JSONObject> objNav = new JSONNavi<>(jsonString, new CustomJsonReader());
54
```
55
56
## Navigation Methods
57
58
### Basic Navigation
59
60
```java { .api }
61
public JSONNavi<T> root();
62
public JSONNavi<?> at(String key);
63
public JSONNavi<?> at(int index);
64
public JSONNavi<?> atNext();
65
public JSONNavi<?> up();
66
public JSONNavi<?> up(int level);
67
```
68
69
Navigate through JSON structures.
70
71
```java
72
String json = """
73
{
74
"users": [
75
{"name": "Alice", "age": 25},
76
{"name": "Bob", "age": 30}
77
],
78
"metadata": {"total": 2}
79
}
80
""";
81
82
JSONNavi<?> nav = new JSONNavi<>(json);
83
84
// Navigate to nested values
85
String firstUserName = nav.at("users").at(0).at("name").asString(); // "Alice"
86
int total = nav.root().at("metadata").at("total").asInt(); // 2
87
88
// Navigate through arrays
89
int bobAge = nav.root().at("users").at(1).at("age").asInt(); // 30
90
91
// Move up in hierarchy
92
JSONNavi<?> usersArray = nav.root().at("users").at(0).up(); // back to users array
93
JSONNavi<?> rootAgain = nav.at("users").up(); // back to root object
94
```
95
96
### Array Navigation
97
98
```java
99
String arrayJson = "[\"apple\", \"banana\", \"cherry\", \"date\"]";
100
JSONNavi<?> nav = new JSONNavi<>(arrayJson);
101
102
// Navigate by index
103
String first = nav.at(0).asString(); // "apple"
104
String third = nav.root().at(2).asString(); // "cherry"
105
106
// Navigate to next positions
107
JSONNavi<?> current = nav.at(0);
108
String second = current.atNext().asString(); // "banana"
109
String fourth = current.atNext().asString(); // "cherry"
110
String fifth = current.atNext().asString(); // "date"
111
```
112
113
## State and Inspection Methods
114
115
```java { .api }
116
public boolean hasFailure();
117
public Object getCurrentObject();
118
public boolean isArray();
119
public boolean isObject();
120
public boolean hasKey(String key);
121
public int getSize();
122
public Collection<String> getKeys();
123
```
124
125
Inspect current navigation state and JSON structure.
126
127
```java
128
JSONNavi<?> nav = new JSONNavi<>("{\"users\": [{\"name\": \"Alice\"}], \"count\": 1}");
129
130
// Check navigation state
131
boolean failed = nav.at("nonexistent").hasFailure(); // true
132
boolean success = nav.root().at("users").hasFailure(); // false
133
134
// Inspect current position
135
nav.at("users");
136
boolean isArr = nav.isArray(); // true
137
boolean isObj = nav.isObject(); // false
138
int size = nav.getSize(); // 1
139
140
nav.root();
141
boolean hasUsers = nav.hasKey("users"); // true
142
boolean hasEmail = nav.hasKey("email"); // false
143
Collection<String> keys = nav.getKeys(); // ["users", "count"]
144
145
// Get current object
146
Object current = nav.at("users").getCurrentObject(); // JSONArray instance
147
Object userObj = nav.at(0).getCurrentObject(); // JSONObject instance
148
```
149
150
## Value Access Methods
151
152
### Direct Value Access
153
154
```java { .api }
155
public Object get(String key);
156
public Object get(int index);
157
public String getString(String key);
158
public int getInt(String key);
159
public Integer getInteger(String key);
160
public double getDouble(String key);
161
```
162
163
Access values from current position without navigation.
164
165
```java
166
String json = """
167
{
168
"user": {
169
"name": "John",
170
"age": 30,
171
"salary": 75000.50,
172
"active": true
173
}
174
}
175
""";
176
177
JSONNavi<?> nav = new JSONNavi<>(json).at("user");
178
179
// Direct access from current position
180
String name = nav.getString("name"); // "John"
181
int age = nav.getInt("age"); // 30
182
double salary = nav.getDouble("salary"); // 75000.50
183
Object active = nav.get("active"); // Boolean true
184
185
// Type-safe access
186
Integer ageObj = nav.getInteger("age"); // Integer 30
187
Integer missing = nav.getInteger("missing"); // null
188
```
189
190
### Current Value Conversion
191
192
```java { .api }
193
public String asString();
194
public int asInt();
195
public Integer asIntegerObj();
196
public long asLong();
197
public Long asLongObj();
198
public double asDouble();
199
public Double asDoubleObj();
200
public float asFloat();
201
public Float asFloatObj();
202
public boolean asBoolean();
203
public Boolean asBooleanObj();
204
```
205
206
Convert current navigation position to specific types.
207
208
```java
209
JSONNavi<?> nav = new JSONNavi<>("[42, \"123\", true, 3.14, null]");
210
211
// Navigate and convert
212
int num1 = nav.at(0).asInt(); // 42
213
int num2 = nav.root().at(1).asInt(); // 123 (string converted to int)
214
boolean bool = nav.root().at(2).asBoolean(); // true
215
double decimal = nav.root().at(3).asDouble(); // 3.14
216
217
// Safe conversion with objects (returns null for invalid/null values)
218
Integer nullValue = nav.root().at(4).asIntegerObj(); // null
219
Boolean validBool = nav.root().at(2).asBooleanObj(); // Boolean.TRUE
220
```
221
222
## Mutation Methods
223
224
### Structure Creation
225
226
```java { .api }
227
public JSONNavi<T> object();
228
public JSONNavi<T> array();
229
```
230
231
Create objects or arrays at current position.
232
233
```java
234
JSONNavi<JSONAwareEx> nav = JSONNavi.newInstance();
235
236
// Create nested structure
237
nav.object() // Create root object
238
.at("users").array() // Create users array
239
.at(0).object() // Create first user object
240
.set("name", "Alice")
241
.set("age", 25);
242
243
String result = nav.toString();
244
// {"users":[{"name":"Alice","age":25}]}
245
```
246
247
### Value Setting
248
249
```java { .api }
250
public JSONNavi<T> set(String key, String value);
251
public JSONNavi<T> set(String key, Number value);
252
public JSONNavi<T> set(String key, int value);
253
public JSONNavi<T> set(String key, long value);
254
public JSONNavi<T> set(String key, double value);
255
public JSONNavi<T> set(String key, float value);
256
public JSONNavi<T> set(String text);
257
public JSONNavi<T> set(Number num);
258
public JSONNavi<T> set(Boolean bool);
259
```
260
261
Set values at current position or by key.
262
263
```java
264
JSONNavi<JSONAwareEx> nav = JSONNavi.newInstance();
265
266
// Create and populate object
267
nav.object()
268
.set("name", "John Doe")
269
.set("age", 30)
270
.set("salary", 75000.50)
271
.set("active", true);
272
273
// Navigate and update
274
nav.at("name").set("John Smith"); // Update existing value
275
nav.root().set("department", "Engineering"); // Add new field
276
277
String json = nav.toString();
278
// {"name":"John Smith","age":30,"salary":75000.5,"active":true,"department":"Engineering"}
279
```
280
281
### Array Operations
282
283
```java { .api }
284
public JSONNavi<T> add(Object... values);
285
```
286
287
Add values to arrays.
288
289
```java
290
JSONNavi<JSONAwareEx> nav = JSONNavi.newInstance();
291
292
// Create array and add elements
293
nav.array()
294
.add("apple", "banana", "cherry")
295
.add(42)
296
.add(true);
297
298
String json = nav.toString();
299
// ["apple","banana","cherry",42,true]
300
301
// Add to existing arrays
302
JSONNavi<?> existing = new JSONNavi<>("[1, 2, 3]");
303
existing.add(4, 5, 6);
304
String updated = existing.toString(); // [1,2,3,4,5,6]
305
```
306
307
## Utility Methods
308
309
```java { .api }
310
public T getRoot();
311
public String getJPath();
312
public String toString();
313
public String toString(JSONStyle compression);
314
```
315
316
Access root object and debugging information.
317
318
```java
319
JSONNavi<?> nav = new JSONNavi<>("{\"a\": {\"b\": [1, 2, {\"c\": \"value\"}]}}");
320
321
// Navigate deep
322
nav.at("a").at("b").at(2).at("c");
323
324
// Get path information
325
String path = nav.getJPath(); // $.a.b[2].c
326
327
// Get root object
328
Object root = nav.getRoot(); // Original JSONObject
329
330
// Serialize current state
331
String json = nav.toString(); // "value" (current position)
332
String rootJson = nav.root().toString(); // Full JSON structure
333
```
334
335
## Usage Examples
336
337
### Dynamic Data Exploration
338
339
```java
340
// Unknown JSON structure
341
String unknownJson = """
342
{
343
"data": {
344
"users": [
345
{"id": 1, "profile": {"name": "Alice", "email": "alice@example.com"}},
346
{"id": 2, "profile": {"name": "Bob", "email": "bob@example.com"}}
347
],
348
"pagination": {"page": 1, "total": 2}
349
}
350
}
351
""";
352
353
JSONNavi<?> nav = new JSONNavi<>(unknownJson);
354
355
// Explore structure
356
if (nav.at("data").hasKey("users")) {
357
int userCount = nav.at("users").getSize();
358
System.out.println("Found " + userCount + " users");
359
360
// Process each user
361
for (int i = 0; i < userCount; i++) {
362
JSONNavi<?> user = nav.at(i);
363
if (user.hasKey("profile")) {
364
String name = user.at("profile").getString("name");
365
String email = user.at("profile").getString("email");
366
System.out.println("User: " + name + " (" + email + ")");
367
}
368
nav.up(); // Back to users array
369
}
370
}
371
```
372
373
### Dynamic JSON Construction
374
375
```java
376
// Build complex JSON structure dynamically
377
JSONNavi<JSONAwareEx> nav = JSONNavi.newInstance();
378
379
nav.object()
380
.set("apiVersion", "v1")
381
.set("timestamp", System.currentTimeMillis())
382
.at("users").array();
383
384
// Add users dynamically
385
String[] names = {"Alice", "Bob", "Charlie"};
386
int[] ages = {25, 30, 35};
387
388
for (int i = 0; i < names.length; i++) {
389
nav.at(i).object()
390
.set("id", i + 1)
391
.set("name", names[i])
392
.set("age", ages[i])
393
.at("roles").array()
394
.add("user");
395
396
if (ages[i] > 30) {
397
nav.add("senior");
398
}
399
400
nav.up().up(); // Back to users array
401
}
402
403
// Add metadata
404
nav.root()
405
.at("metadata").object()
406
.set("userCount", names.length)
407
.set("generated", true);
408
409
String result = nav.toString();
410
```
411
412
### Error-Safe Navigation
413
414
```java
415
String json = "{\"user\": {\"profile\": {\"name\": \"John\"}}}";
416
JSONNavi<?> nav = new JSONNavi<>(json);
417
418
// Chain navigation with error checking
419
String name = null;
420
if (!nav.at("user").hasFailure() &&
421
!nav.at("profile").hasFailure() &&
422
!nav.at("name").hasFailure()) {
423
name = nav.asString();
424
}
425
426
// Alternative: check at each step
427
nav.root();
428
if (nav.hasKey("user")) {
429
nav.at("user");
430
if (nav.hasKey("profile")) {
431
nav.at("profile");
432
name = nav.getString("name");
433
}
434
}
435
436
// Or use try-catch approach
437
try {
438
String safeName = nav.root().at("user").at("profile").at("name").asString();
439
} catch (Exception e) {
440
// Handle navigation failure
441
System.out.println("Failed to get user name: " + e.getMessage());
442
}
443
```
444
445
### Array Processing
446
447
```java
448
String arrayJson = """
449
[
450
{"name": "Alice", "score": 95, "active": true},
451
{"name": "Bob", "score": 87, "active": false},
452
{"name": "Charlie", "score": 92, "active": true}
453
]
454
""";
455
456
JSONNavi<?> nav = new JSONNavi<>(arrayJson);
457
458
// Process array elements
459
int size = nav.getSize();
460
JSONArray activeUsers = new JSONArray();
461
462
for (int i = 0; i < size; i++) {
463
JSONNavi<?> user = nav.at(i);
464
boolean active = user.getBoolean("active");
465
466
if (active) {
467
String name = user.getString("name");
468
int score = user.getInt("score");
469
470
JSONObject activeUser = new JSONObject()
471
.appendField("name", name)
472
.appendField("score", score);
473
activeUsers.appendElement(activeUser);
474
}
475
476
nav.up(); // Back to root array
477
}
478
479
String activeUsersJson = JSONValue.toJSONString(activeUsers);
480
```
481
482
### Conditional Modifications
483
484
```java
485
JSONNavi<?> nav = new JSONNavi<>("{\"users\": [], \"settings\": {}}");
486
487
// Conditionally modify structure
488
nav.at("users");
489
if (nav.getSize() == 0) {
490
// Add default user if array is empty
491
nav.add(new JSONObject()
492
.appendField("name", "Default User")
493
.appendField("role", "guest"));
494
}
495
496
nav.root().at("settings");
497
if (!nav.hasKey("theme")) {
498
nav.set("theme", "light");
499
}
500
501
if (!nav.hasKey("notifications")) {
502
nav.set("notifications", true);
503
}
504
505
String updated = nav.root().toString();
506
```