如何在Java中从相对路径读取JSON文件

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

Introduction

In Java programming, working with JSON (JavaScript Object Notation) data is an essential skill for modern development. JSON has become the standard format for data exchange in web applications and APIs due to its simplicity and readability.

This tutorial will guide you through the complete process of reading JSON files from a relative path in your Java applications. You will learn how to set up the necessary dependencies, create JSON files, read them from relative paths, and parse the data for use in your applications.

By the end of this lab, you will be able to confidently work with JSON data in your Java projects, which is a fundamental skill for any Java developer working with web services, APIs, or configuration files.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/FileandIOManagementGroup(["File and I/O Management"]) java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java/BasicSyntaxGroup -.-> java/output("Output") java/StringManipulationGroup -.-> java/strings("Strings") java/DataStructuresGroup -.-> java/arrays("Arrays") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/encapsulation("Encapsulation") java/FileandIOManagementGroup -.-> java/files("Files") java/FileandIOManagementGroup -.-> java/read_files("Read Files") java/FileandIOManagementGroup -.-> java/io("IO") subgraph Lab Skills java/output -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/strings -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/arrays -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/classes_objects -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/encapsulation -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/files -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/read_files -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} java/io -.-> lab-417587{{"如何在Java中从相对路径读取JSON文件"}} end

Understanding JSON and Setting Up Your Project

What is JSON?

JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write, and easy for machines to parse and generate. JSON is built on two structures:

  • A collection of name/value pairs (similar to a dictionary or object)
  • An ordered list of values (similar to an array or list)

Here's a simple example of a JSON object:

{
  "name": "John",
  "age": 30,
  "isStudent": false,
  "courses": ["Java", "Python", "JavaScript"]
}

Project Setup

For this lab, we'll be using the org.json library, which is a widely used library for working with JSON in Java. The library has already been added to your project through Maven.

Let's verify the project setup by opening the pom.xml file:

  1. In the WebIDE, open the file explorer panel on the left side.
  2. Navigate to the ~/project directory.
  3. Open the pom.xml file by clicking on it.

You should see the following dependency in the pom.xml file:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20230227</version>
</dependency>

This dependency includes the org.json library in our project, which provides classes like JSONObject and JSONArray that we'll use to work with JSON data.

Creating Our First Java Class

Now, let's create a simple Java class to test our setup:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file JsonTester.java.
  4. Add the following code to the file:
import org.json.JSONObject;

public class JsonTester {
    public static void main(String[] args) {
        // Create a simple JSON object
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", "Hello, JSON!");

        // Print the JSON object
        System.out.println("JSON Object: " + jsonObject.toString());
    }
}

This simple class creates a JSON object with a single key-value pair and prints it to the console.

Compiling and Running the Program

Now, let's compile and run our program to make sure everything is set up correctly:

  1. Open a terminal in the WebIDE.
  2. Navigate to the project directory:
cd ~/project
  1. Compile the Java class using Maven:
mvn compile
  1. Run the program:
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) JsonTester

You should see output similar to this:

JSON Object: {"message":"Hello, JSON!"}

This confirms that our project is set up correctly and we can work with JSON in Java.

Creating a Simple JSON File

In this step, we'll create a JSON file that we can later read from our Java application. We'll place this file in the resources directory, which is a common location for storing configuration files and other resources in Java projects.

Creating the JSON File

Let's create a simple JSON file with some data:

  1. In the WebIDE, navigate to ~/project/src/main/resources.
  2. Right-click on the resources folder and select "New File".
  3. Name the file data.json.
  4. Add the following JSON content to the file:
{
  "name": "John Doe",
  "age": 28,
  "email": "john.doe@example.com",
  "isEmployed": true,
  "address": {
    "street": "123 Main St",
    "city": "Anytown",
    "zipCode": "12345"
  },
  "skills": ["Java", "SQL", "JavaScript", "HTML"]
}

This JSON file represents a person with various attributes, including nested data (the address object) and an array of skills.

Understanding the JSON Structure

Let's break down the structure of this JSON file:

  • The file contains a single JSON object (enclosed in {}).
  • The object has several properties:
    • Simple properties: name (string), age (number), email (string), isEmployed (boolean)
    • A nested object: address, which has its own properties (street, city, zipCode)
    • An array: skills, which contains a list of strings

Understanding this structure will be important when we parse the JSON data in our Java application.

Verifying the JSON File

To ensure that our JSON file is valid, let's create a simple Java program to check it:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file JsonValidator.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class JsonValidator {
    public static void main(String[] args) {
        try {
            // Get the absolute path to the resources directory
            String resourcesPath = new File("src/main/resources").getAbsolutePath();
            System.out.println("Resources directory: " + resourcesPath);

            // Path to the JSON file
            String jsonFilePath = resourcesPath + "/data.json";
            System.out.println("JSON file path: " + jsonFilePath);

            // Check if the file exists
            File jsonFile = new File(jsonFilePath);
            if (jsonFile.exists()) {
                System.out.println("JSON file exists.");

                // Read the contents of the file
                String jsonContent = new String(Files.readAllBytes(Paths.get(jsonFilePath)));

                // Parse the JSON to validate it
                JSONObject jsonObject = new JSONObject(jsonContent);
                System.out.println("JSON is valid.");
                System.out.println("Person's name: " + jsonObject.getString("name"));
            } else {
                System.out.println("JSON file does not exist at the specified path.");
            }
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This program performs several important checks:

  • It finds the absolute path to our resources directory
  • It checks if our JSON file exists
  • It reads the file content and attempts to parse it as a JSON object
  • It extracts and prints the person's name from the JSON data

Let's run this program to verify our JSON file:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) JsonValidator

You should see output similar to this:

Resources directory: /home/labex/project/src/main/resources
JSON file path: /home/labex/project/src/main/resources/data.json
JSON file exists.
JSON is valid.
Person's name: John Doe

This confirms that our JSON file exists, is valid, and can be parsed in Java.

Reading JSON Files from Relative Paths

Now that we have a valid JSON file, let's learn how to read it from a relative path within our Java application. Using relative paths is a good practice because it makes your code more portable across different environments.

Understanding Relative Paths in Java

A relative path is specified relative to the current working directory. In Java applications, the current working directory is typically the root directory of your project (in our case, ~/project).

For example, if our working directory is ~/project, then the relative path to our JSON file would be src/main/resources/data.json.

Creating a JSON Reader Class

Let's create a Java class that reads our JSON file from a relative path:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file JsonReader.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class JsonReader {
    public static void main(String[] args) {
        try {
            // Specify the relative path to the JSON file
            String filePath = "src/main/resources/data.json";

            // Print the current working directory for reference
            System.out.println("Current working directory: " + System.getProperty("user.dir"));
            System.out.println("Trying to read JSON from: " + filePath);

            // Read the contents of the JSON file
            String jsonData = new String(Files.readAllBytes(Paths.get(filePath)));

            // Print the raw JSON data
            System.out.println("\nRaw JSON data:");
            System.out.println(jsonData);

            // Parse the JSON data into a JSONObject
            JSONObject jsonObject = new JSONObject(jsonData);

            // Access basic JSON data
            String name = jsonObject.getString("name");
            int age = jsonObject.getInt("age");
            String email = jsonObject.getString("email");
            boolean isEmployed = jsonObject.getBoolean("isEmployed");

            // Print the extracted data
            System.out.println("\nExtracted data:");
            System.out.println("Name: " + name);
            System.out.println("Age: " + age);
            System.out.println("Email: " + email);
            System.out.println("Employed: " + isEmployed);

            System.out.println("\nJSON file has been successfully read and parsed.");
        } catch (IOException e) {
            System.out.println("Error reading JSON file: " + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("Error parsing JSON: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This class:

  1. Defines a relative path to our JSON file
  2. Prints the current working directory for reference
  3. Reads the contents of the file using Files.readAllBytes
  4. Parses the JSON data into a JSONObject
  5. Extracts and prints some of the data from the JSON object

Platform-Independent Path Handling

The code above uses forward slashes (/) for the file path, which works on both Unix-based systems (Linux, macOS) and Windows. However, for a more platform-independent approach, you can use the File.separator constant:

String filePath = "src" + File.separator + "main" + File.separator + "resources" + File.separator + "data.json";

This ensures that the correct path separator is used regardless of the operating system.

Running the JSON Reader

Let's run our JSON Reader program:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) JsonReader

You should see output similar to this:

Current working directory: /home/labex/project
Trying to read JSON from: src/main/resources/data.json

Raw JSON data:
{
  "name": "John Doe",
  "age": 28,
  "email": "john.doe@example.com",
  "isEmployed": true,
  "address": {
    "street": "123 Main St",
    "city": "Anytown",
    "zipCode": "12345"
  },
  "skills": ["Java", "SQL", "JavaScript", "HTML"]
}

Extracted data:
Name: John Doe
Age: 28
Email: john.doe@example.com
Employed: true

JSON file has been successfully read and parsed.

This confirms that we've successfully read our JSON file from a relative path and extracted some of the data.

Using Class Resources for Path Independence

Another common approach for reading files in Java applications is to use the class loader to access resources on the classpath. This approach is especially useful for JAR files and deployed applications.

Let's create another class that demonstrates this approach:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file ClasspathJsonReader.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;

public class ClasspathJsonReader {
    public static void main(String[] args) {
        try {
            // Get the resource as an input stream
            InputStream inputStream = ClasspathJsonReader.class.getClassLoader().getResourceAsStream("data.json");

            if (inputStream == null) {
                System.out.println("Could not find data.json on the classpath");
                return;
            }

            // Read the input stream into a string
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder jsonData = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                jsonData.append(line).append("\n");
            }

            // Parse the JSON data
            JSONObject jsonObject = new JSONObject(jsonData.toString());

            // Print some data
            System.out.println("Name: " + jsonObject.getString("name"));
            System.out.println("Age: " + jsonObject.getInt("age"));

            System.out.println("JSON file successfully read from classpath.");
        } catch (IOException e) {
            System.out.println("Error reading JSON file: " + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("Error parsing JSON: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This method will work regardless of the working directory, as long as the file is on the classpath. However, we need to compile first to make the resources available on the classpath:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) ClasspathJsonReader

You might not see the expected output because the resources aren't properly copied to the classpath during a simple compile. For a production application, you would use mvn package to create a JAR file with all resources included.

Parsing and Handling Complex JSON Structures

In the previous steps, we learned how to read a JSON file and access its basic properties. Now, let's explore how to handle more complex JSON structures, such as nested objects and arrays.

Our data.json file contains a nested object (address) and an array (skills). In this step, we'll create a Java program that accesses these complex structures.

Creating a Complex JSON Parser

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file ComplexJsonParser.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import org.json.JSONArray;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ComplexJsonParser {
    public static void main(String[] args) {
        try {
            // Read the JSON file
            String filePath = "src/main/resources/data.json";
            String jsonData = new String(Files.readAllBytes(Paths.get(filePath)));

            // Parse the JSON data
            JSONObject person = new JSONObject(jsonData);

            // Print the person's basic information
            System.out.println("Person Information:");
            System.out.println("-------------------");
            System.out.println("Name: " + person.getString("name"));
            System.out.println("Age: " + person.getInt("age"));
            System.out.println("Email: " + person.getString("email"));
            System.out.println("Employed: " + person.getBoolean("isEmployed"));

            // Access the nested address object
            JSONObject address = person.getJSONObject("address");
            System.out.println("\nAddress Information:");
            System.out.println("-------------------");
            System.out.println("Street: " + address.getString("street"));
            System.out.println("City: " + address.getString("city"));
            System.out.println("Zip Code: " + address.getString("zipCode"));

            // Access the skills array
            JSONArray skills = person.getJSONArray("skills");
            System.out.println("\nSkills:");
            System.out.println("-------");
            for (int i = 0; i < skills.length(); i++) {
                System.out.println("- " + skills.getString(i));
            }

            // Demonstrating error handling: Trying to access a non-existent field
            try {
                String phoneNumber = person.getString("phoneNumber");
                System.out.println("Phone: " + phoneNumber);
            } catch (Exception e) {
                System.out.println("\nNote: The 'phoneNumber' field doesn't exist in the JSON data.");
            }

        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This program:

  1. Reads and parses the JSON data
  2. Accesses the basic person information
  3. Accesses the nested address object using getJSONObject()
  4. Accesses the skills array using getJSONArray() and iterates through it
  5. Demonstrates error handling when trying to access a non-existent field

Running the Complex JSON Parser

Let's run our program:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) ComplexJsonParser

You should see output similar to this:

Person Information:
-------------------
Name: John Doe
Age: 28
Email: john.doe@example.com
Employed: true

Address Information:
-------------------
Street: 123 Main St
City: Anytown
Zip Code: 12345

Skills:
-------
- Java
- SQL
- JavaScript
- HTML

Note: The 'phoneNumber' field doesn't exist in the JSON data.

Creating a More Complex JSON File

Now, let's create a more complex JSON file to practice with:

  1. In the WebIDE, navigate to ~/project/src/main/resources.
  2. Right-click on the resources folder and select "New File".
  3. Name the file company.json.
  4. Add the following JSON content to the file:
{
  "companyName": "Tech Innovators Inc.",
  "founded": 2005,
  "location": {
    "city": "San Francisco",
    "state": "CA",
    "country": "USA"
  },
  "isPublic": true,
  "employees": [
    {
      "id": 1,
      "name": "Alice Johnson",
      "position": "CEO",
      "department": "Executive",
      "skills": ["Leadership", "Strategy", "Public Speaking"]
    },
    {
      "id": 2,
      "name": "Bob Smith",
      "position": "CTO",
      "department": "Engineering",
      "skills": ["Java", "Architecture", "AI"]
    },
    {
      "id": 3,
      "name": "Carol Williams",
      "position": "Developer",
      "department": "Engineering",
      "skills": ["Java", "Python", "JavaScript"]
    }
  ],
  "departments": ["Executive", "Engineering", "Marketing", "Sales"],
  "annualRevenue": {
    "2020": 1500000,
    "2021": 1800000,
    "2022": 2200000
  }
}

This JSON file represents a company with nested objects, arrays, and arrays of objects.

Creating a Parser for the Complex Company JSON

Let's create a program to parse this more complex JSON:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file CompanyJsonParser.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import org.json.JSONArray;
import java.nio.file.Files;
import java.nio.file.Paths;

public class CompanyJsonParser {
    public static void main(String[] args) {
        try {
            // Read the JSON file
            String filePath = "src/main/resources/company.json";
            String jsonData = new String(Files.readAllBytes(Paths.get(filePath)));

            // Parse the JSON data
            JSONObject company = new JSONObject(jsonData);

            // Print the company's basic information
            System.out.println("Company Information:");
            System.out.println("--------------------");
            System.out.println("Name: " + company.getString("companyName"));
            System.out.println("Founded: " + company.getInt("founded"));
            System.out.println("Public: " + company.getBoolean("isPublic"));

            // Access the nested location object
            JSONObject location = company.getJSONObject("location");
            System.out.println("\nLocation:");
            System.out.println("--------");
            System.out.println("City: " + location.getString("city"));
            System.out.println("State: " + location.getString("state"));
            System.out.println("Country: " + location.getString("country"));

            // Access the departments array
            JSONArray departments = company.getJSONArray("departments");
            System.out.println("\nDepartments:");
            System.out.println("------------");
            for (int i = 0; i < departments.length(); i++) {
                System.out.println("- " + departments.getString(i));
            }

            // Access the employees array of objects
            JSONArray employees = company.getJSONArray("employees");
            System.out.println("\nEmployees:");
            System.out.println("---------");
            for (int i = 0; i < employees.length(); i++) {
                JSONObject employee = employees.getJSONObject(i);
                System.out.println("\nEmployee #" + employee.getInt("id"));
                System.out.println("Name: " + employee.getString("name"));
                System.out.println("Position: " + employee.getString("position"));
                System.out.println("Department: " + employee.getString("department"));

                // Access the skills array for each employee
                JSONArray skills = employee.getJSONArray("skills");
                System.out.println("Skills:");
                for (int j = 0; j < skills.length(); j++) {
                    System.out.println("  - " + skills.getString(j));
                }
            }

            // Access the annual revenue object
            JSONObject revenue = company.getJSONObject("annualRevenue");
            System.out.println("\nAnnual Revenue:");
            System.out.println("--------------");
            for (String year : revenue.keySet()) {
                System.out.println(year + ": $" + revenue.getInt(year));
            }

        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This program:

  1. Reads and parses the complex company JSON data
  2. Accesses the basic company information
  3. Accesses the nested location object
  4. Iterates through the departments array
  5. Iterates through the employees array, which contains objects
  6. For each employee, accesses their basic information and iterates through their skills array
  7. Iterates through the annual revenue data by year

Running the Company JSON Parser

Let's run our program:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) CompanyJsonParser

You should see detailed output showing all the information parsed from the complex company JSON structure.

Creating a Reusable JSON Utility Class

In this final step, we'll create a reusable JSON utility class that encapsulates the functionality for reading and parsing JSON files. This is a best practice in software development, as it promotes code reuse and separation of concerns.

Creating the JSON Utility Class

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file JsonUtils.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import org.json.JSONArray;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * Utility class for handling JSON operations.
 */
public class JsonUtils {

    /**
     * Reads a JSON file from a relative path and returns it as a JSONObject.
     *
     * @param filePath The relative path to the JSON file
     * @return The JSONObject representing the file contents
     * @throws IOException If there's an error reading the file
     */
    public static JSONObject readJsonObjectFromFile(String filePath) throws IOException {
        String jsonData = new String(Files.readAllBytes(Paths.get(filePath)));
        return new JSONObject(jsonData);
    }

    /**
     * Reads a JSON file from a relative path and returns it as a JSONArray.
     *
     * @param filePath The relative path to the JSON file
     * @return The JSONArray representing the file contents
     * @throws IOException If there's an error reading the file
     */
    public static JSONArray readJsonArrayFromFile(String filePath) throws IOException {
        String jsonData = new String(Files.readAllBytes(Paths.get(filePath)));
        return new JSONArray(jsonData);
    }

    /**
     * Gets a string value from a JSONObject, or returns a default value if the key doesn't exist.
     *
     * @param jsonObject The JSONObject to extract from
     * @param key The key to look for
     * @param defaultValue The default value to return if the key doesn't exist
     * @return The string value or the default value
     */
    public static String getString(JSONObject jsonObject, String key, String defaultValue) {
        return jsonObject.has(key) ? jsonObject.getString(key) : defaultValue;
    }

    /**
     * Gets an integer value from a JSONObject, or returns a default value if the key doesn't exist.
     *
     * @param jsonObject The JSONObject to extract from
     * @param key The key to look for
     * @param defaultValue The default value to return if the key doesn't exist
     * @return The integer value or the default value
     */
    public static int getInt(JSONObject jsonObject, String key, int defaultValue) {
        return jsonObject.has(key) ? jsonObject.getInt(key) : defaultValue;
    }

    /**
     * Gets a boolean value from a JSONObject, or returns a default value if the key doesn't exist.
     *
     * @param jsonObject The JSONObject to extract from
     * @param key The key to look for
     * @param defaultValue The default value to return if the key doesn't exist
     * @return The boolean value or the default value
     */
    public static boolean getBoolean(JSONObject jsonObject, String key, boolean defaultValue) {
        return jsonObject.has(key) ? jsonObject.getBoolean(key) : defaultValue;
    }

    /**
     * Extracts a list of strings from a JSONArray.
     *
     * @param jsonArray The JSONArray to extract from
     * @return A List of strings
     */
    public static List<String> getStringList(JSONArray jsonArray) {
        List<String> result = new ArrayList<>();
        for (int i = 0; i < jsonArray.length(); i++) {
            result.add(jsonArray.getString(i));
        }
        return result;
    }

    /**
     * Pretty-prints a JSONObject.
     *
     * @param jsonObject The JSONObject to print
     * @return A formatted string representation of the JSONObject
     */
    public static String prettyPrint(JSONObject jsonObject) {
        return jsonObject.toString(4);  // Indent with 4 spaces
    }

    /**
     * Pretty-prints a JSONArray.
     *
     * @param jsonArray The JSONArray to print
     * @return A formatted string representation of the JSONArray
     */
    public static String prettyPrint(JSONArray jsonArray) {
        return jsonArray.toString(4);  // Indent with 4 spaces
    }
}

This utility class provides several methods:

  • readJsonObjectFromFile: Reads a JSON file and returns it as a JSONObject
  • readJsonArrayFromFile: Reads a JSON file and returns it as a JSONArray
  • Several getter methods with default values to safely extract data from a JSONObject
  • A method to convert a JSONArray of strings to a List<String>
  • Pretty-printing methods for both JSONObject and JSONArray

Creating a Test Class for Our JSON Utility

Now, let's create a class to test our JSON utility:

  1. In the WebIDE, navigate to ~/project/src/main/java.
  2. Right-click on the java folder and select "New File".
  3. Name the file JsonUtilsDemo.java.
  4. Add the following code to the file:
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.List;

public class JsonUtilsDemo {
    public static void main(String[] args) {
        try {
            // Read the person JSON file using our utility
            System.out.println("Reading person data...");
            JSONObject person = JsonUtils.readJsonObjectFromFile("src/main/resources/data.json");

            // Using our utility methods to safely extract data
            String name = JsonUtils.getString(person, "name", "Unknown");
            int age = JsonUtils.getInt(person, "age", 0);
            String email = JsonUtils.getString(person, "email", "No email");
            boolean isEmployed = JsonUtils.getBoolean(person, "isEmployed", false);

            // Using a default value for a non-existent field
            String phone = JsonUtils.getString(person, "phoneNumber", "No phone number");

            System.out.println("Person Information:");
            System.out.println("Name: " + name);
            System.out.println("Age: " + age);
            System.out.println("Email: " + email);
            System.out.println("Employed: " + isEmployed);
            System.out.println("Phone: " + phone);  // Will show the default value

            // Access the skills array and convert it to a List
            JSONArray skillsArray = person.getJSONArray("skills");
            List<String> skills = JsonUtils.getStringList(skillsArray);

            System.out.println("\nSkills:");
            for (String skill : skills) {
                System.out.println("- " + skill);
            }

            // Read the company JSON file
            System.out.println("\nReading company data...");
            JSONObject company = JsonUtils.readJsonObjectFromFile("src/main/resources/company.json");

            // Pretty-print the company data
            System.out.println("\nCompany Data (Pretty-Printed):");
            System.out.println(JsonUtils.prettyPrint(company));

            // Extract and display the employees
            JSONArray employees = company.getJSONArray("employees");
            System.out.println("\nEmployees (Pretty-Printed):");
            System.out.println(JsonUtils.prettyPrint(employees));

        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

This program:

  1. Uses our JsonUtils class to read the person and company JSON files
  2. Uses the safe getter methods to extract data with default values
  3. Converts a JSON array to a Java List
  4. Uses the pretty-print methods to display formatted JSON data

Running the JSON Utils Demo

Let's run our demo program:

cd ~/project
mvn compile
java -cp target/classes:$(mvn dependency:build-classpath -q -Dmdep.outputFile=/dev/stdout) JsonUtilsDemo

You should see output that demonstrates all the features of our JSON utility class, including pretty-printed JSON data.

The Benefits of a Reusable Utility Class

Creating a reusable utility class for JSON operations offers several benefits:

  1. Code Reuse: You don't have to repeat the same JSON parsing code in multiple places.
  2. Error Handling: You can implement consistent error handling in one place.
  3. Default Values: You can provide default values for missing JSON fields, making your code more robust.
  4. Encapsulation: The details of JSON parsing are encapsulated within the utility class.
  5. Maintainability: If the JSON library changes or you want to switch to a different one, you only need to update the utility class.

In a real-world application, you might want to extend this utility class with additional functionality, such as:

  • Writing JSON data to files
  • Converting between JSON and Java objects (serialization/deserialization)
  • Validating JSON against a schema
  • Handling more complex data types

Summary of What We've Learned

Throughout this lab, we've learned:

  1. The basics of JSON and how it's used in Java
  2. How to set up a Java project with JSON dependencies
  3. How to create and validate JSON files
  4. How to read JSON files from relative paths
  5. How to parse and handle complex JSON structures
  6. How to create a reusable utility class for JSON operations

These skills will be valuable in many Java development scenarios, from working with RESTful APIs to handling configuration files and data storage.

Summary

In this lab, you have learned how to work with JSON data in Java applications, specifically focusing on reading JSON files from relative paths. Here's a summary of what you've accomplished:

  1. You set up a Java project with the necessary JSON dependencies and created your first simple JSON object.

  2. You created JSON files with varying complexity and verified their validity.

  3. You learned how to read JSON files from relative paths using both standard file operations and the classpath approach.

  4. You explored how to parse and handle complex JSON structures, including nested objects and arrays.

  5. You created a reusable JSON utility class that encapsulates common JSON operations and makes your code more maintainable.

These skills are foundational for Java developers working with modern applications that exchange data with web services, APIs, and other systems. JSON has become the standard format for data exchange in modern web development, and the ability to efficiently work with JSON in Java is a crucial skill.

As you continue your Java development journey, you can build on these skills to implement more advanced features, such as:

  • Converting between JSON and Java objects using libraries like Jackson or Gson
  • Working with RESTful APIs that exchange JSON data
  • Implementing JSON Web Tokens (JWT) for authentication
  • Creating JSON-based configuration systems

The knowledge you've gained in this lab provides a solid foundation for these advanced topics.