### Custom JSONPath Functions and Operators in Java Source: https://context7.com/noear/snackjson/llms.txt Extend JSONPath querying capabilities in SnackJSON by registering custom functions and operators. This example demonstrates how to add a 'floor' function for numeric values and a 'startsWith' operator for string comparisons. It involves using `FunctionLib`, `OperatorLib`, and SnackJSON's `ONode` for expression evaluation. Input is typically a JSON string or `ONode`, and output is an `ONode` representing the query result. ```java import snackjson.core.ONode; import snackjson.core.FunctionLib; import snackjson.core.OperatorLib; // Register custom floor function FunctionLib.register("floor", (ctx, argNodes) -> { ONode arg0 = argNodes.get(0); if (ctx.isDescendant()) { for (ONode n1 : arg0.getArray()) { if (n1.isNumber()) { n1.setValue(Math.floor(n1.getDouble())); } } return arg0; } else { ONode n1 = arg0.get(0); if (n1.isNumber()) { return ctx.newNode(Math.floor(n1.getDouble())); } else { return ctx.newNode(); } } }); // Use custom function ONode result = ONode.ofJson("{\"a\":3.7,\"b\":8.2}").select("$.a.floor()"); System.out.println(result.toJson()); // Output: 3.0 // Register custom operator OperatorLib.register("startsWith", (ctx, node, term) -> { ONode leftNode = term.getLeftNode(ctx, node); if (leftNode.isString()) { ONode rightNode = term.getRightNode(ctx, node); if (rightNode.isNull()) { return false; } return leftNode.getString().startsWith(rightNode.getString()); } return false; }); // Use custom operator ONode data = ONode.ofJson("{\"list\":[\"apple\",\"banana\",\"avocado\"]}"); ONode filtered = data.select("$.list[?@ startsWith 'a']"); System.out.println(filtered.toJson()); // Output: ["apple","avocado"] ``` -------------------------------- ### JSONPath IETF Standard Functions Source: https://github.com/noear/snackjson/blob/main/README.md Standard functions include 'length(x)' to get the size of strings, arrays, or objects, and 'count(x)' to determine the number of nodes in a node list. 'match(x,y)' performs regular expression matching. ```jsonpath length(x) count(x) match(x,y) ``` -------------------------------- ### JSONPath Array Slice and Filter Selectors Source: https://github.com/noear/snackjson/blob/main/README.md Array slicing (e.g., '0:100:5') allows for extracting portions of arrays based on start, end, and step. Filter selectors ('?') enable selection of nodes based on specified conditions, often involving other nodes or functions. ```jsonpath 0:100:5 ? ``` -------------------------------- ### Parsing and Creating JSON with ONode API in Java Source: https://context7.com/noear/snackjson/llms.txt Demonstrates how to parse JSON strings into ONode objects, create JSON structures programmatically, and build nested JSON objects and arrays using the SnackJson framework. It covers parsing from strings and Java beans, and programmatic construction. ```java import com.fasterxml.jackson.databind.type.TypeReference; import org.noear.snack.ONode; import java.util.Arrays; import java.util.List; import java.util.Map; // Assume User and Address classes are defined elsewhere as per the example class User { public String name; public int age; public boolean active; public List roles; public Address address; } class Address { public String city; public String country; } public class SnackJsonExamples { public void parseAndCreateJson() { // Parse JSON from string ONode node = ONode.ofJson("{\"name\":\"John\",\"age\":30,\"active\":true}"); // Parse from bean/object User user = new User(); user.name = "Alice"; user.age = 25; ONode userNode = ONode.ofBean(user); // Create JSON programmatically ONode obj = new ONode(); obj.set("id", 1001); obj.set("name", "Product"); obj.set("price", 99.99); obj.set("inStock", true); // Build nested structures ONode order = new ONode(); order.set("orderId", "ORD-12345"); order.getOrNew("customer").then(c -> { c.set("name", "John Doe"); c.set("email", "john@example.com"); }); order.getOrNew("items").then(items -> { items.addNew().set("product", "Laptop").set("quantity", 1); items.addNew().set("product", "Mouse").set("quantity", 2); }); String json = order.toJson(); System.out.println("Constructed JSON: " + json); // Output: {"orderId":"ORD-12345","customer":{"name":"John Doe","email":"john@example.com"},"items":[{"product":"Laptop","quantity":1},{"product":"Mouse","quantity":2}]} } public void accessAndManipulateJson() { // Load complex JSON ONode data = ONode.ofJson("{\"code\":1,\"msg\":\"Success\",\"data\":{\"users\":[{\"id\":1,\"name\":\"Alice\",\"age\":30},{\"id\":2,\"name\":\"Bob\",\"age\":25}]}}"); // Access nested values int code = data.get("code").getInt(); String message = data.get("msg").getString(); String firstName = data.get("data").get("users").get(0).get("name").getString(); System.out.println("Code: " + code + ", Message: " + message + ", First User Name: " + firstName); // Type checks boolean isObject = data.get("data").isObject(); boolean isArray = data.get("data").get("users").isArray(); boolean isNull = data.get("missing").isNull(); System.out.println("Is data object: " + isObject + ", Is users array: " + isArray + ", Is missing null: " + isNull); // Modify values data.get("data").get("users").get(0).set("age", 31); data.set("timestamp", System.currentTimeMillis()); // Array operations ONode users = data.get("data").get("users"); users.addNew().set("id", 3).set("name", "Charlie").set("age", 28); users.remove(0); // Remove first element // Safe navigation with defaults int defaultAge = data.get("data").get("users").get(0).get("age").getInt(18); // Assuming first user exists after removal String middleName = data.get("middleName").getString("N/A"); System.out.println("Modified data: " + data.toJson()); System.out.println("Default age for first user: " + defaultAge + ", Middle name: " + middleName); } public void serializeAndDeserializeJson() { // Serialize to JSON User user = new User(); user.name = "Alice"; user.age = 30; user.active = true; user.roles = Arrays.asList("admin", "user"); user.address = new Address(); user.address.city = "New York"; user.address.country = "USA"; String json = ONode.serialize(user); // or String json2 = ONode.ofBean(user).toJson(); System.out.println("Serialized user JSON: " + json); // Deserialize from JSON String jsonString = "{\"name\":\"Bob\",\"age\":25,\"active\":false,\"roles\":[\"guest\"],\"address\":{\"city\":\"London\",\"country\":\"UK\"}}"; User deserializedUser = ONode.deserialize(jsonString, User.class); System.out.println("Deserialized user name: " + deserializedUser.name + ", city: " + deserializedUser.address.city); // Generic collections List userList = ONode.ofJson("[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]") .toBean(new TypeReference>() {}); System.out.println("Deserialized user list size: " + userList.size()); // Map handling Map map = ONode.ofJson("{\"key1\":\"value1\",\"key2\":123}") .toBean(new TypeReference>() {}); System.out.println("Deserialized map value for key1: " + map.get("key1")); } public static void main(String[] args) { SnackJsonExamples examples = new SnackJsonExamples(); examples.parseAndCreateJson(); examples.accessAndManipulateJson(); examples.serializeAndDeserializeJson(); } } ``` -------------------------------- ### Path Tree Navigation in SnackJSON Java Source: https://context7.com/noear/snackjson/llms.txt Explore how to track and navigate node paths within JSON structures using SnackJSON in Java. This includes automatically generating path lists when using the `select` method and manually constructing paths by traversing the node tree. Functions like `pathList()`, `path()`, `parent()`, and `usePaths()` are demonstrated. Input is a JSON string or `ONode`, and outputs are path strings or parent `ONode` objects. ```java import snackjson.core.ONode; import java.util.List; // Automatic path generation with select ONode data = ONode.ofJson("{\"data\":{\"users\":[{\"name\":\"Alice\",\"mobile\":\"123\"},{\"name\":\"Bob\",\"mobile\":\"456\"}]}}"); ONode result = data.select("$.data.users[*].mobile"); List paths = result.pathList(); // Returns: ["$.data.users[0].mobile", "$.data.users[1].mobile"] for (ONode node : result.getArray()) { System.out.println("Path: " + node.path()); System.out.println("Value: " + node.getString()); System.out.println("Parent: " + node.parent().toJson()); } // Manual path generation ONode root = ONode.ofJson("{\"level1\":{\"level2\":{\"value\":\"data\"}}}").usePaths(); ONode deepNode = root.get("level1").get("level2").get("value"); System.out.println(deepNode.path()); // Output: $.level1.level2.value System.out.println(deepNode.parent().path()); // Output: $.level1.level2 System.out.println(deepNode.parent().parent().path()); // Output: $.level1 ``` -------------------------------- ### Custom Serialization with Encoders and Decoders in Java Source: https://context7.com/noear/snackjson/llms.txt Learn to extend SnackJSON's serialization process by defining custom encoders for specific data types and decoders for parsing them back from JSON. This includes configuring serialization features like pretty printing and handling null or unknown fields. Dependencies include `java.util.Date`, `java.text.SimpleDateFormat`, and SnackJSON's `Options`, `ONode`, `Feature` classes. ```java import java.util.Date; import java.text.SimpleDateFormat; import snackjson.core.ONode; import snackjson.core.Options; import snackjson.core.Feature; // Create custom options with encoders/decoders Options options = Options.of(); // Add custom date encoder options.addEncoder(Date.class, (ctx, value, target) -> { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); target.setValue(sdf.format((Date) value)); }); // Add custom date decoder options.addDecoder(Date.class, (ctx, source, target) -> { if (source.isString()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return sdf.parse(source.getString()); } catch (java.text.ParseException e) { // Handle parsing error appropriately return null; } } return null; }); // Configure features options.addFeature(Feature.Write_PrettyFormat); // Pretty print JSON options.addFeature(Feature.Write_EnumUsingName); // Use enum names instead of ordinals options.addFeature(Feature.Write_IgnoreNull); // Skip null fields options.addFeature(Feature.Read_IgnoreUnknown); // Ignore unknown fields // Use custom options class Event { public String name; public Date timestamp; public Status status; } enum Status { PENDING, ACTIVE, COMPLETED } Event event = new Event(); event.name = "Meeting"; event.timestamp = new Date(); event.status = Status.ACTIVE; String json = ONode.ofBean(event, options).toJson(); // Output with pretty format and custom date format: // { // "name": "Meeting", // "timestamp": "2025-12-09 10:30:00", // "status": "ACTIVE" // } Event decoded = ONode.ofJson(json, options).toBean(Event.class); ``` -------------------------------- ### JSONPath Jayway Extension Operators Source: https://github.com/noear/snackjson/blob/main/README.md Jayway's JSONPath implementation extends standard operators with regular expression matching (=~), membership testing (in, nin), subset checking (subsetof, anyof, noneof), size validation (size), and emptiness check (empty). ```jsonpath =~ in nin subsetof anyof noneof size empty ``` -------------------------------- ### JSONPath Child and Descendant Segment Selectors Source: https://github.com/noear/snackjson/blob/main/README.md Child segments like '[]' and '.name' select direct children, while descendant segments like '..[]' and '..name' recursively select children at any depth. Wildcards like '.*' and '..*' are used for selecting all children. ```jsonpath [] .name .* ..[] ..name ..* ``` -------------------------------- ### JSONPath Name, Wildcard, and Index Selectors Source: https://github.com/noear/snackjson/blob/main/README.md These selectors target specific elements within JSON. Name selectors (''name'') target named object properties. Wildcard selectors ('*') select all children. Index selectors ('3') target array elements by their numerical position (0-based). ```jsonpath 'name' * 3 ``` -------------------------------- ### JSONPath IETF Standard Comparison Operators Source: https://github.com/noear/snackjson/blob/main/README.md The IETF JSONPath standard defines equality (==, !=), and inequality (<, <=, >, >=) operators for comparing values. Note that type coercion is not performed, so '1' is not equal to '1'. ```jsonpath == != < <= > >= ``` -------------------------------- ### JSONPath Filter Expression Syntax Source: https://github.com/noear/snackjson/blob/main/README.md Filter expressions support grouping with parentheses, function calls, logical NOT (!), relational operators (==, !=, <, <=, >, >=), logical AND (&&), and logical OR (||). These operators have defined precedence levels. ```jsonpath (...) name(...) ! ==,!=,<,<=,>,>= && || ``` -------------------------------- ### JSONPath Root and Current Node Identifiers Source: https://github.com/noear/snackjson/blob/main/README.md The '$' symbol represents the root node of the JSON document, while '@' is used within filter selectors to refer to the current node being processed. These are fundamental for navigating JSON structures. ```jsonpath $ @ ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.