|
35 | 35 | import com.google.gson.JsonParser;
|
36 | 36 | import com.google.gson.JsonSyntaxException;
|
37 | 37 | import com.jayway.jsonpath.JsonPath;
|
| 38 | +import com.jayway.jsonpath.PathNotFoundException; |
38 | 39 | import com.networknt.schema.JsonSchema;
|
39 | 40 | import com.networknt.schema.JsonSchemaFactory;
|
40 | 41 | import com.networknt.schema.SpecVersion;
|
@@ -347,6 +348,111 @@ public static JsonObject getJsonObjectFromString(String jsonString) {
|
347 | 348 | return JsonParser.parseString(jsonString).getAsJsonObject();
|
348 | 349 | }
|
349 | 350 |
|
| 351 | + /** |
| 352 | + * Checks if a specified JSON path exists within a given JSON object. |
| 353 | + * |
| 354 | + * This method attempts to read the value at the specified path in the JSON object. |
| 355 | + * If the path exists, it returns true. If a PathNotFoundException is thrown, |
| 356 | + * indicating that the path does not exist, it returns false. |
| 357 | + * |
| 358 | + * @param json The JSON object to check. This can be a Map, List, or any object |
| 359 | + * that JsonPath can parse. |
| 360 | + * @param path The JSON path to check for existence. This should be a valid |
| 361 | + * JsonPath expression (e.g., "$.store.book[0].title"). |
| 362 | + * @return true if the path exists in the JSON object, false otherwise. |
| 363 | + * @throws IllegalArgumentException if the json object is null or if the path is null or empty. |
| 364 | + */ |
| 365 | + public static boolean pathExists(Object json, String path) { |
| 366 | + if (json == null) { |
| 367 | + throw new IllegalArgumentException("JSON object cannot be null"); |
| 368 | + } |
| 369 | + if (path == null || path.isEmpty()) { |
| 370 | + throw new IllegalArgumentException("Path cannot be null or empty"); |
| 371 | + } |
| 372 | + if (!isValidJSONPath(path)) { |
| 373 | + throw new IllegalArgumentException("the field path is not a valid json path: " + path); |
| 374 | + } |
| 375 | + try { |
| 376 | + JsonPath.read(json, path); |
| 377 | + return true; |
| 378 | + } catch (PathNotFoundException e) { |
| 379 | + return false; |
| 380 | + } |
| 381 | + } |
| 382 | + |
| 383 | + /** |
| 384 | + * Prepares nested structures in a JSON object based on the given field path. |
| 385 | + * |
| 386 | + * This method ensures that all intermediate nested objects and arrays exist in the JSON object |
| 387 | + * for a given field path. If any part of the path doesn't exist, it creates new empty objects |
| 388 | + * (HashMaps) or arrays (ArrayLists) for those parts. |
| 389 | + * |
| 390 | + * The method can handle complex paths including both object properties and array indices. |
| 391 | + * For example, it can process paths like "foo.bar[1].baz[0].qux". |
| 392 | + * |
| 393 | + * @param jsonObject The JSON object to be updated. If this is not a Map, a new Map will be created. |
| 394 | + * @param fieldPath The full path of the field, potentially including nested structures and array indices. |
| 395 | + * The path can optionally start with "$." which will be ignored if present. |
| 396 | + * @return The updated JSON object with necessary nested structures in place. |
| 397 | + * If the input was not a Map, returns the newly created Map structure. |
| 398 | + * |
| 399 | + * @throws IllegalArgumentException If the field path is null or not a valid JSON path. |
| 400 | + * |
| 401 | + */ |
| 402 | + public static Object prepareNestedStructures(Object jsonObject, String fieldPath) { |
| 403 | + if (fieldPath == null) { |
| 404 | + throw new IllegalArgumentException("The field path is null"); |
| 405 | + } |
| 406 | + if (jsonObject == null) { |
| 407 | + throw new IllegalArgumentException("The object is null"); |
| 408 | + } |
| 409 | + if (!isValidJSONPath(fieldPath)) { |
| 410 | + throw new IllegalArgumentException("The field path is not a valid JSON path: " + fieldPath); |
| 411 | + } |
| 412 | + |
| 413 | + String path = fieldPath.startsWith("$.") ? fieldPath.substring(2) : fieldPath; |
| 414 | + String[] pathParts = path.split("(?<!\\\\)\\."); |
| 415 | + |
| 416 | + Map<String, Object> current = (jsonObject instanceof Map) ? (Map<String, Object>) jsonObject : new HashMap<>(); |
| 417 | + |
| 418 | + for (String part : pathParts) { |
| 419 | + if (part.contains("[")) { |
| 420 | + // Handle array notation |
| 421 | + String[] arrayParts = part.split("\\["); |
| 422 | + String key = arrayParts[0]; |
| 423 | + int index = Integer.parseInt(arrayParts[1].replaceAll("\\]", "")); |
| 424 | + |
| 425 | + if (!current.containsKey(key)) { |
| 426 | + current.put(key, new ArrayList<>()); |
| 427 | + } |
| 428 | + if (!(current.get(key) instanceof List)) { |
| 429 | + return jsonObject; |
| 430 | + } |
| 431 | + List<Object> list = (List<Object>) current.get(key); |
| 432 | + if (index >= list.size()) { |
| 433 | + while (list.size() <= index) { |
| 434 | + list.add(null); |
| 435 | + } |
| 436 | + list.set(index, new HashMap<>()); |
| 437 | + } |
| 438 | + if (!(list.get(index) instanceof Map)) { |
| 439 | + return jsonObject; |
| 440 | + } |
| 441 | + current = (Map<String, Object>) list.get(index); |
| 442 | + } else { |
| 443 | + // Handle object notation |
| 444 | + if (!current.containsKey(part)) { |
| 445 | + current.put(part, new HashMap<>()); |
| 446 | + } else if (!(current.get(part) instanceof Map)) { |
| 447 | + return jsonObject; |
| 448 | + } |
| 449 | + current = (Map<String, Object>) current.get(part); |
| 450 | + } |
| 451 | + } |
| 452 | + |
| 453 | + return jsonObject; |
| 454 | + } |
| 455 | + |
350 | 456 | public static void validateSchema(String schemaString, String instanceString) {
|
351 | 457 | try {
|
352 | 458 | // parse the schema JSON as string
|
|
0 commit comments