Json

  • Find the Sum of the First Two Elements in a List in Java 8

    Problem:
    Using Java 8 Streams, how do you find the sum of the first two numbers in a list?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class SumOfFirstTwoNumbers {
    
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(87, 45, 35, 74, 325);
    
            int sumOfTwoNumbers = numbers.stream()
                    .limit(2)  // Take first two elements
                    .mapToInt(Integer::intValue)  // Convert to int stream
                    .sum();  // Calculate the sum
    
            System.out.println("Sum of first two numbers = " + sumOfTwoNumbers);
        }
    }
    

    ✅ Output:

    Sum of first two numbers = 132

    ✅ Explanation:

    1. The list of numbers: [87, 45, 35, 74, 325]
    2. .stream() creates a stream of elements from the list.
    3. .limit(2) restricts the stream to the first two elements: [87, 45].
    4. .mapToInt(Integer::intValue) converts Integer to primitive int for summing.
    5. .sum() computes the sum of the two numbers:
      87 + 45 = 132.
    6. Finally, print the result: System.out.println("Sum of first two numbers = " + sumOfTwoNumbers);

  • Find the First Repeating Character in a String in Java

    Problem:
    Using Java 8 Streams, how do you find the first repeating character in a given string?

    ✅ Example:

    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class FindFirstRepeatingCharacter {
    
        public static void main(String[] args) {
            String input = "repeating-characters";
    
            input.chars()
                    .mapToObj(ch -> (char) ch)
                    .collect(Collectors.groupingBy(
                            ch -> ch,
                            LinkedHashMap::new,  // Preserve insertion order
                            Collectors.counting()))
                    .entrySet()
                    .stream()
                    .filter(entry -> entry.getValue() > 1)  // Find characters appearing more than once
                    .map(Map.Entry::getKey)
                    .findFirst()
                    .ifPresent(System.out::println);
        }
    }
    

    ✅ Output:

    e

    ✅ Explanation:

    1. Step 1 – Convert String to Character Stream: input.chars().mapToObj(ch -> (char) ch)
      • Converts the string "repeating-characters" to a stream of characters.
    2. Step 2 – Group by Character Count: .collect(Collectors.groupingBy( ch -> ch, LinkedHashMap::new, Collectors.counting()))
      • Creates a LinkedHashMap<Character, Long> where the key is the character and the value is the count of occurrences.
      • LinkedHashMap preserves the order of first appearance.
    3. Step 3 – Filter Repeating Characters: .filter(entry -> entry.getValue() > 1)
      • Keeps only characters that occur more than once.
    4. Step 4 – Pick First Repeating Character: .findFirst()
      • Finds the first character (in the original order) that repeats.
    5. Step 5 – Print the Character: ifPresent(System.out::println);
  • Find the First Non-Repeating Character in a String

    Problem:
    Using Java 8 Streams, how do you find the first non-repeating character in a given string?

    ✅ Example:

    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class FirstNonRepeatingCharacter {
    
        public static void main(String[] args) {
            String input = "Shubham";
    
            input.chars()
                    .mapToObj(ch -> (char) ch)
                    .collect(Collectors.groupingBy(
                            ch -> ch,
                            LinkedHashMap::new,  // Maintain insertion order
                            Collectors.counting()))
                    .entrySet()
                    .stream()
                    .filter(entry -> entry.getValue() == 1)  // Filter non-repeating characters
                    .map(Map.Entry::getKey)
                    .findFirst()
                    .ifPresent(System.out::println);
        }
    }
    

    ✅ Output:

    S

    ✅ Explanation:

    1. Step 1 – Convert String to Stream of Characters: input.chars().mapToObj(ch -> (char) ch)
      • Converts the string "Shubham" into a stream of characters:
        ['S', 'h', 'u', 'b', 'h', 'a', 'm'].
    2. Step 2 – Group by Character Count: .collect(Collectors.groupingBy( ch -> ch, LinkedHashMap::new, Collectors.counting()))
      • Groups characters into a LinkedHashMap<Character, Long>, maintaining insertion order, and counting occurrences.
    3. Step 3 – Filter Non-Repeating Characters: .filter(entry -> entry.getValue() == 1)
      • Keeps only characters that appear exactly once.
    4. Step 4 – Get First Non-Repeating Character: .findFirst()
      • Returns the first non-repeating character (if present).
    5. Step 5 – Print Result: ifPresent(System.out::println);
  • Count the Occurrence of Each Character in a String in Java

    Problem:
    Using Java 8 Streams, how do you count the number of occurrences of each character in a given string (ignoring spaces)?

    ✅ Example:

    import java.util.Arrays;
    import java.util.Map;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    
    public class CharacterCount {
    
        public static void main(String[] args) {
            String input = "Hello Everyone";
    
            Map<String, Long> charToCount = Arrays.stream(input.replaceAll("\\s+", "").split(""))
                    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    
            charToCount.forEach((character, count) ->
                    System.out.println("Character: " + character + ", Count: " + count));
        }
    }
    

    ✅ Example Output:

    Character: H, Count: 1  
    Character: e, Count: 4  
    Character: l, Count: 2  
    Character: o, Count: 2  
    Character: v, Count: 1  
    Character: r, Count: 1  
    Character: y, Count: 1  
    Character: n, Count: 1  
    

    ✅ Explanation:

    1. Normalization Step: input.replaceAll("\\s+", "")
      • Removes all spaces from the input string "Hello Everyone""HelloEveryone".
    2. Splitting into Characters: .split("")
      • Splits the string into individual characters: ["H", "e", "l", "l", "o", "E", "v", "e", "r", "y", "o", "n", "e"].
    3. Stream Processing: Arrays.stream(...)
      • Converts the array of characters into a stream.
    4. Grouping and Counting: .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
      • Groups characters by themselves and counts the number of occurrences.
    5. Printing the Result: charToCount.forEach((character, count) -> System.out.println(...));
  • Find the 3rd Longest Word in a List in Java

    Problem:
    Using Java 8 Streams, how do you find the third longest word in a list without manually sorting and looping through?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class ThirdLongestWord {
    
        public static void main(String[] args) {
            List<String> words = Arrays.asList("apple", "banana", "cherry", "mango", "kiwi");
    
            words.stream()
                    .sorted((w1, w2) -> Integer.compare(w2.length(), w1.length()))  // Sort by length descending
                    .skip(2)  // Skip the first two longest words
                    .findFirst()  // Get the 3rd longest word
                    .ifPresent(System.out::println);
        }
    }
    

    ✅ Output:

    apple

    ✅Explanation:

    1. The list of words: ["apple", "banana", "cherry", "mango", "kiwi"]
    2. After sorting by length in descending order: ["banana", "cherry", "apple", "mango", "kiwi"]
    3. .skip(2) skips the first two words:
      • Skips "banana" and "cherry".
    4. .findFirst() picks the next word:
      • Which is "apple".
    5. The output is printed: apple

  • Find the First Odd Number from a List in Java

    Problem:
    Using Java 8 Streams, how do you find the first odd number in a list efficiently, without manually looping?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    
    public class FirstOddNumber {
    
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(2, 4, 6, 8, 17, 9, 24, 19);
    
            Optional<Integer> firstOdd = numbers.stream()  // Use stream(), parallelStream() is not necessary here
                    .filter(element -> element % 2 != 0)  // Filter odd numbers
                    .findFirst();  // Find the first matching element
    
            firstOdd.ifPresent(System.out::println);
        }
    }
    

    ✅ Output:

    17

    ✅ ✅ Explanation:

    1. We create a list of numbers: [2, 4, 6, 8, 17, 9, 24, 19]
    2. We use .stream() (sequential stream is sufficient for this purpose): numbers.stream()
    3. .filter(ele -> ele % 2 != 0) filters all odd numbers:
      • Result after filtering: [17, 9, 19].
    4. .findFirst() returns the first element in encounter order, wrapped in Optional<Integer>.
    5. We print the result using: firstOdd.ifPresent(System.out::println);

    ✅ Important Note:

    • Avoid using .parallelStream() here because it may not guarantee order in finding the first element.
      Always prefer .stream() when order matters.

  • Java 8 Streams – Find the Nth Largest Element in an Array

    Problem:
    How can you find the 3rd largest element from an integer array using Java 8 Streams?

    ✅ Correct Code Example:

    import java.util.Arrays;
    import java.util.Comparator;
    
    public class NthLargestElement {
    
        public static void main(String[] args) {
            int[] arr = {12, 4, 3, 1, 9, 657};
            int n = 3;  // Find the 3rd largest element
    
            Arrays.stream(arr)
                    .boxed()  // Convert int to Integer for Comparator
                    .sorted(Comparator.reverseOrder())  // Sort in descending order
                    .skip(n - 1)  // Skip first (n - 1) largest elements
                    .findFirst()  // Get the nth largest element
                    .ifPresent(System.out::println);
        }
    }
    

    ✅ ✅ Example Output:

    9
    

    ✅ ✅ Explanation:

    1. Step 1 – Stream Creation: Arrays.stream(arr) Creates an IntStream from the integer array [12, 4, 3, 1, 9, 657].
    2. Step 2 – Boxing: .boxed() Converts IntStream to Stream<Integer> so we can use Comparator.reverseOrder().
    3. Step 3 – Sorting in Descending Order: .sorted(Comparator.reverseOrder()) After sorting, the stream becomes: [657, 12, 9, 4, 3, 1].
    4. Step 4 – Skip Elements: .skip(n - 1) Skip the first two elements (657 and 12) to get to the 3rd largest.
    5. Step 5 – Get the Nth Largest: .findFirst() Picks the next element in the stream, which is 9.
    6. Step 6 – Print Result: ifPresent(System.out::println);

    ✅ Using Scanner for System Input:

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.Scanner;
    
    public class NthLargestElement {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
    
            int[] arr = {12, 4, 3, 1, 9, 657};
    
            System.out.print("Enter the value of n (e.g., 3 for 3rd largest): ");
            int n = scanner.nextInt();
    
            if (n <= 0 || n > arr.length) {
                System.out.println("Invalid input! n must be between 1 and " + arr.length);
            } else {
                Arrays.stream(arr)
                        .boxed()  // Convert int to Integer for Comparator
                        .sorted(Comparator.reverseOrder())  // Sort in descending order
                        .skip(n - 1)  // Skip first (n - 1) elements
                        .findFirst()  // Pick the nth largest element
                        .ifPresent(System.out::println);
            }
    
            scanner.close();
        }
    }
    

    ✅ Sample Run Example:

    Input (User types):

    3
    

    Output:

    9
    

    ✅ Explanation:

    1. We use Scanner to take user input for n.
    2. We validate n to ensure it is within the correct range: if (n <= 0 || n > arr.length)
    3. We apply the same stream logic:
      • Sort in descending order.
      • Skip the first (n - 1) elements.
      • Return the nth largest element.
    4. The result is printed using .ifPresent(System.out::println).

  • Filter Strings Starting with a Number

    Problem:
    Given a list of strings, how do you filter only those strings that start with a digit using Java 8 Streams?

    ✅Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class StringStartingWithNumber {
    
        public static void main(String[] args) {
            List<String> list = Arrays.asList("TOrange", "Banana", "2Papaya", "Grapes", "3Pineapple", "Cherry");
    
            list.stream()
                .filter(str -> !str.isEmpty() && Character.isDigit(str.charAt(0)))
                .forEach(System.out::println);
        }
    }
    

    ✅Output:

    2Papaya
    3Pineapple
    

    ✅Explanation:

    1. We define a list of strings: ["TOrange", "Banana", "2Papaya", "Grapes", "3Pineapple", "Cherry"]
    2. We create a stream from the list: list.stream()
    3. The filter() condition: str -> !str.isEmpty() && Character.isDigit(str.charAt(0))
      • Ensures the string is not empty.
      • Checks whether the first character is a digit using Character.isDigit(str.charAt(0)).
    4. The filtered strings are printed using: forEach(System.out::println);
  • Find Numbers Starting with the digit ‘1’

    Problem:
    Given a list of integers (which may contain null values), filter out all the numbers that start with the digit '1' using Java 8 Streams.

    ✅Example:

    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class NumbersStartingWithOne {
    
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(123, null, null, 345, 765, 1876, 90, 100);
    
            List<Integer> numbersStartingWithOne = numbers.stream()
                    .filter(num -> num != null && String.valueOf(num).startsWith("1"))
                    .collect(Collectors.toList());
    
            numbersStartingWithOne.forEach(System.out::println);
        }
    }
    

    ✅ Example Output:

    123
    1876
    100

    ✅ Explanation:

    • The list of numbers is: [123, null, null, 345, 765, 1876, 90, 100].
    • We use numbers.stream() to create a stream.
    • The filter() condition: num -> num != null && String.valueOf(num).startsWith("1")
      • Skips null values to avoid NullPointerException.
      • Converts the number to a string and checks if it starts with '1'.
    • .collect(Collectors.toList()) collects the filtered numbers into a new list.
    • Finally, numbersStartingWithOne.forEach(System.out::println); prints: 123 1876 100

  • Jackson Tree Model (JsonNode) – Complete JSON Guide

    When working with JSON, the most common approach is to bind JSON data directly to Java POJOs (Plain Old Java Objects) using Jackson’s data binding feature. However, sometimes the structure of the incoming JSON is dynamic, unknown, or too flexible to predefine Java classes.
    In these cases, Jackson’s Tree Model API comes in handy by allowing us to parse JSON into a tree structure that can be traversed dynamically.

    1.What Is the Tree Model (JsonNode)?

    • The Tree Model allows us to parse JSON into a tree of JsonNode objects.
    • Each JsonNode represents a part of the JSON data:
      • ObjectNode → Represents a JSON object { ... }.
      • ArrayNode → Represents a JSON array [ ... ].
      • ValueNode → Represents JSON values (strings, numbers, booleans, null).

    This approach treats the JSON structure like a tree, allowing traversal, dynamic access, and even modification of individual nodes.

    2. Why Use the Tree Model?

    • 👉 Useful when the JSON structure is unpredictable or changes frequently.
    • 👉 Allows selective data extraction without having to map the entire JSON to a predefined class.
    • 👉 Facilitates reading deeply nested properties or arrays in a flexible manner.
    • 👉 Supports modifications before re-serializing the data back to JSON.

    3. How to Parse JSON into Tree Model using JsonNode

    ✔️ Example JSON:
    {
        "name": "Ashish Kumar",
        "age": 30,
        "address": {
            "city": "Delhi",
            "zipcode": "110001"
        },
        "skills": ["Java", "Spring Boot", "Jackson"]
    }
    
    ✔️Example Java Code:
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JacksonTreeModelExample {
      public static void main(String[] args) {
        try {
          String json = "{ \"name\": \"Ashish Kumar\", \"age\": 30, \"address\": { \"city\": \"Delhi\", \"zipcode\": \"110001\" }, \"skills\": [\"Java\", \"Spring Boot\", \"Jackson\"] }";
    
          ObjectMapper objectMapper = new ObjectMapper();
    
          // Parse JSON into a tree of JsonNode
          JsonNode rootNode = objectMapper.readTree(json);
    
          // Access simple properties
          String name = rootNode.get("name").asText();
          int age = rootNode.get("age").asInt();
    
          System.out.println("Name: " + name);
          System.out.println("Age: " + age);
    
          // Access nested object
          JsonNode addressNode = rootNode.get("address");
          String city = addressNode.get("city").asText();
          String zipcode = addressNode.get("zipcode").asText();
          System.out.println("City: " + city);
          System.out.println("Zipcode: " + zipcode);
    
          // Access array
          JsonNode skillsNode = rootNode.get("skills");
          System.out.print("Skills: ");
          for (JsonNode skill: skillsNode) {
            System.out.print(skill.asText() + ",");
          }
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
    }
    ✔️ Expected Output:
    Name: Ashish Kumar  
    Age: 30  
    City: Delhi  
    Zipcode: 110001  
    Skills: Java Spring Boot Jackson 
    
    Detailed Explanation of the Process
    1. Parsing JSON:
      • objectMapper.readTree(json) reads the entire JSON string and creates a tree of JsonNode objects.
      • rootNode represents the root of the tree.
    2. Accessing Simple Properties:
      • rootNode.get("name").asText() extracts the "name" property as a String.
      • rootNode.get("age").asInt() extracts the "age" property as an integer.
    3. Accessing a Nested Object:
      • rootNode.get("address") returns a JsonNode representing the "address" object.
      • Then we extract individual fields from addressNode:
        • addressNode.get("city").asText()
        • addressNode.get("zipcode").asText()
    4. Accessing Array Elements:
      • rootNode.get("skills") returns a JsonNode representing the JSON array.
      • Iterating through the array elements using a for-each loop and accessing each skill’s value with skill.asText().

    ✅ Advantages of Tree Model

    AdvantageExplanation
    Dynamic ParsingNo need to create Java classes in advance. Useful for unknown or changing JSON structures.
    Selective Data AccessAccess only the parts of the JSON you need, saving memory and effort.
    Nested and Array SupportEasily traverse deeply nested objects and arrays without mapping everything upfront.

    ✅ When to Use Tree Model vs Data Binding

    ScenarioRecommended Approach
    Static and well-defined structureUse POJOs + ObjectMapper (Serialization/Deserialization)
    Unknown, dynamic, or partial structureUse Tree Model (JsonNode)
    Need to modify part of the JSONUse ObjectNode (which extends JsonNode) to manipulate fields

    4. Creating JSON Objects Dynamically with ObjectNode

    In some scenarios, you don’t have a predefined Java object (POJO) to represent the JSON you want to generate.
    For example, when building dynamic JSON responses in REST APIs, or transforming data on the fly.
    Jackson’s ObjectNode class is ideal for such cases.

    ✅ What Is ObjectNode?

    • ObjectNode is a subclass of JsonNode that represents a JSON object { ... }.
    • Allows you to dynamically create, modify, and remove fields without needing a POJO.
    • Ideal when you want to construct a JSON object programmatically

    Example :

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ArrayNode;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    
    public class DynamicJsonExample {
        public static void main(String[] args) throws Exception {
            ObjectMapper objectMapper = new ObjectMapper();
    
            // Create the root JSON object
            ObjectNode jsonObject = objectMapper.createObjectNode();
    
            // Add simple fields
            jsonObject.put("name", "Ashish Kumar");
            jsonObject.put("age", 30);
    
            // Add nested address object
            ObjectNode addressNode = objectMapper.createObjectNode();
            addressNode.put("city", "Delhi");
            addressNode.put("zipcode", "110001");
            jsonObject.set("address", addressNode);
    
            // Add skills array
            ArrayNode skillsArray = objectMapper.createArrayNode();
            skillsArray.add("Java");
            skillsArray.add("Spring Boot");
            skillsArray.add("Jackson");
            jsonObject.set("skills", skillsArray);
    
            // Output the pretty-printed JSON string
            System.out.println(jsonObject.toPrettyString());
        }
    }

    Explanation :

    Output :

    {
      "name" : "Ashish Kumar",
      "age" : 30,
      "address" : {
        "city" : "Delhi",
        "zipcode" : "110001"
      },
      "skills" : [ "Java", "Spring Boot", "Jackson" ]
    }

    📌Why This Example Is Useful

    • ✅ Demonstrates how to create simple fields using put().
    • ✅ Shows how to add a nested object with ObjectNode.
    • ✅ Explains how to build an array field using ArrayNode.
    • ✅ Illustrates use cases like building dynamic JSON responses in REST APIs, building configuration files dynamically, or performing data transformations.

    5. Working with JSON Arrays in Java

    A JSON Array is an ordered collection of values, which may include objects, strings, numbers, booleans, or other primitives. In Java, using Jackson, you can easily parse and construct JSON arrays with the help of the ArrayNode class, which extends JsonNode.

    ✔️ Example JSON Array
    [
        {"productId": 101, "productName": "Wireless Mouse", "price": 25.99},
        {"productId": 102, "productName": "Mechanical Keyboard", "price": 75.49}
    ]

    5.1 Parsing JSON Arrays with Jackson

    Imagine you receive a JSON array from an external API that lists products available in an online store. You can parse the JSON array string into an ArrayNode and iterate through its elements like this:

    String jsonArrayString = "[" +
        "{\"productId\": 101, \"productName\": \"Wireless Mouse\", \"price\": 1899.00}," +
        "{\"productId\": 102, \"productName\": \"Mechanical Keyboard\", \"price\": 5499.00}" +
        "]";
    
    ArrayNode jsonArray = (ArrayNode) objectMapper.readTree(jsonArrayString);
    
    for (JsonNode product : jsonArray) {
        System.out.println("Product ID: " + product.get("productId").asInt());
        System.out.println("Product Name: " + product.get("productName").asText());
        System.out.println("Price: ₹" + product.get("price").asDouble());
        System.out.println("-----------------------------------");
    }
    
    ✔️ Example output:
    Product ID: 101
    Product Name: Wireless Mouse
    Price: ₹1899.0
    -----------------------------------
    Product ID: 102
    Product Name: Mechanical Keyboard
    Price: ₹5499.0
    -----------------------------------

    5.2 Constructing JSON Arrays Dynamically

    Suppose your application needs to dynamically build a product catalog before returning it as a JSON response. You can use ArrayNode to construct the array programmatically:

    ArrayNode productsArray = objectMapper.createArrayNode();
    
    ObjectNode product1 = objectMapper.createObjectNode()
        .put("productId", 201)
        .put("productName", "USB-C Charger")
        .put("price", 999.00);
    
    ObjectNode product2 = objectMapper.createObjectNode()
        .put("productId", 202)
        .put("productName", "Noise Cancelling Headphones")
        .put("price", 7499.00);
    
    productsArray.add(product1);
    productsArray.add(product2);
    
    System.out.println(productsArray.toString());
    

    ✔ Example output:

    [
        {"productId":201,"productName":"USB-C Charger","price":999.0},
        {"productId":202,"productName":"Noise Cancelling Headphones","price":7499.0}
    ]
    

    👉 In a real-time e-commerce system, this dynamic creation of product lists allows you to build flexible APIs that respond with the most up-to-date product information in INR.

    6. Choosing Between ArrayNode and JsonNode

    When working with JSON data using Jackson, knowing when to use ArrayNode versus JsonNode helps you write cleaner, more efficient, and maintainable code.

    ✅ Use ArrayNode when:

    • You are working with a JSON structure where you know the data is always an array.
    • You need to perform specific operations on array elements, such as filtering, sorting, or mapping.
    • The structure is well-defined, and you want to work directly with array-specific methods (like .add(), .remove(), .size(), etc.).

    ✅ Use JsonNode when:

    • You are dealing with dynamic or nested JSON structures, where some fields could be arrays, objects, or primitive values.
    • You need a flexible and generic approach to process JSON without assuming a strict structure.
    • You want to parse arbitrary JSON data and explore it at runtime, especially when the schema is not predefined.

    👉 Choosing the right type between ArrayNode and JsonNode helps improve code clarity and performance in your application.

    7. Difference Between get()and path() in Jackson Tree Model

    When working with the Jackson Tree Model (JsonNode), you often need to access specific fields or nested data in a JSON structure. Two commonly used methods for this are .get() and .path(). Understanding their differences helps you write more robust and error-resistant code.

    7.1 get(String fieldName)

    • Behavior: Returns the value of the specified field as a JsonNode.
    • If the field does not exist: It returns null.
    • Use Case: When you are sure the field exists and want to get the exact node.

    Example:

    JsonNode nameNode = rootNode.get("name");  // returns null if "name" field is missing

    ⚠️ Risk: If you immediately call .asText() or .asInt() after .get(), and the field does not exist (i.e., null is returned), you will get a NullPointerException.

    7.2 path(String fieldName)

    • Behavior: Returns the value of the specified field as a JsonNode.
    • If the field does not exist: Returns a missing node (MissingNode), which is a special JsonNode that does not throw NullPointerException and safely returns default values.

    Example:

    JsonNode nameNode = rootNode.path("name");  // Returns MissingNode if "name" does not exist
    String name = nameNode.asText();            // Returns "" (empty string) if missing

    Advantages of path()

    1. Safe Access Without NullPointerException
      Even if the field doesn’t exist, path() ensures that your code doesn’t throw a NullPointerException. Instead, it returns a MissingNode, and calling .asText(), .asInt(), etc., returns sensible defaults:
      • .asText()""
      • .asInt() 0
    2. More Robust for Dynamic or Uncertain JSON Structures
      In real-world applications where the JSON structure might change or fields may be missing, using .path() prevents your code from breaking unexpectedly.

    ✅ Example Comparison

    // Using get() – Potential NullPointerException
    String name = rootNode.get("name").asText();        // Works if "name" exists
    String phone = rootNode.get("phone").asText();    // Throws NullPointerException if "phone" is missing
    
    // Using path() – Safe even if field missing
    String name = rootNode.path("name").asText();     // Returns "Ashish Kumar"
    String phone = rootNode.path("phone").asText();   // Returns "" (empty string)

    Note :

    📦 When Was path() Introduced?

    The path() method has been available since early versions of Jackson (introduced around Jackson 2.x series) and has become a standard best practice for safely accessing JSON tree nodes when the presence of fields is not guaranteed.

    🎯 Conclusion

    Jackson’s Tree Model API is a powerful and flexible approach for handling JSON data in Java, especially when working with dynamic, unknown, or partially structured JSON. Unlike the traditional POJO-based data binding approach, the Tree Model provides the ability to parse JSON into a tree of JsonNode objects, enabling dynamic traversal, selective data access, and easy manipulation of JSON content.

    By using ObjectNode and ArrayNode, developers can dynamically construct JSON objects and arrays programmatically, making it ideal for use cases such as building REST API responses or handling configuration files. Furthermore, the choice between .get() and .path() methods ensures safer and more robust handling of potentially missing fields in JSON data.

    In summary, when dealing with unpredictable or frequently changing JSON structures, leveraging the Tree Model approach offers maximum flexibility, reduces boilerplate code, and improves the maintainability of your Java applications. Always prefer path() over get() in uncertain scenarios to avoid NullPointerException and ensure more stable code execution.