杰瑞科技汇

Java如何将JSON数据转换为Excel文件?

Of course! Converting JSON to Excel in Java is a common task. The most popular and robust way to do this is by using the Apache POI library for Excel and a JSON library like Jackson or Gson to parse the JSON data.

Java如何将JSON数据转换为Excel文件?-图1
(图片来源网络,侵删)

Here’s a complete guide, from a simple example to a more robust and reusable solution.

Recommended Tools & Libraries

  1. Apache POI: The de-facto standard for creating and manipulating Microsoft Office formats, including Excel (.xlsx).
  2. Jackson: A high-performance JSON processor for Java. It's widely used and has excellent features for mapping JSON to Java objects.

You'll need to add these dependencies to your project.


Step 1: Add Dependencies

For Maven (pom.xml)

<dependencies>
    <!-- For creating Excel files (.xlsx) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.5</version> <!-- Use the latest version -->
    </dependency>
    <!-- For parsing JSON -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.17.0</version> <!-- Use the latest version -->
    </dependency>
</dependencies>

For Gradle (build.gradle)

dependencies {
    // For creating Excel files (.xlsx)
    implementation 'org.apache.poi:poi-ooxml:5.2.5' // Use the latest version
    // For parsing JSON
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0' // Use the latest version
}

Step 2: The Java Code

We'll explore two common scenarios:

  1. Simple Conversion: A JSON array of objects where each object becomes a row in Excel.
  2. Robust Conversion: Handling more complex JSON structures (nested objects, arrays) and writing them to a single sheet.

Scenario 1: Simple JSON Array to Excel

This is the most straightforward case. Let's assume you have a JSON string that looks like this:

Java如何将JSON数据转换为Excel文件?-图2
(图片来源网络,侵删)

data.json

[
  {
    "id": 1,
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "age": 30
  },
  {
    "id": 2,
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@example.com",
    "age": 25
  },
  {
    "id": 3,
    "firstName": "Peter",
    "lastName": "Jones",
    "email": "peter.jones@example.com",
    "age": 40
  }
]

Here is the Java code to convert this into an Excel file named output.xlsx.

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class JsonToExcelConverter {
    public static void main(String[] args) {
        // 1. JSON Input
        String jsonFilePath = "data.json";
        String excelFilePath = "output.xlsx";
        try {
            // 2. Parse JSON to a List of Maps
            ObjectMapper objectMapper = new ObjectMapper();
            List<Map<String, Object>> jsonData = objectMapper.readValue(new File(jsonFilePath), new TypeReference<List<Map<String, Object>>>() {});
            // 3. Create Excel Workbook and Sheet
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("Sheet1");
            // 4. Create Header Row
            Row headerRow = sheet.createRow(0);
            // Get headers from the keys of the first map
            Map<String, Object> firstRow = jsonData.get(0);
            int cellIndex = 0;
            for (String key : firstRow.keySet()) {
                Cell cell = headerRow.createCell(cellIndex++);
                cell.setCellValue(key);
            }
            // 5. Create Data Rows
            int rowIndex = 1;
            for (Map<String, Object> rowData : jsonData) {
                Row row = sheet.createRow(rowIndex++);
                cellIndex = 0;
                for (Object value : rowData.values()) {
                    Cell cell = row.createCell(cellIndex++);
                    // Set cell value based on its type
                    if (value instanceof String) {
                        cell.setCellValue((String) value);
                    } else if (value instanceof Integer) {
                        cell.setCellValue((Integer) value);
                    } else if (value instanceof Double) {
                        cell.setCellValue((Double) value);
                    } else if (value instanceof Boolean) {
                        cell.setCellValue((Boolean) value);
                    } else {
                        cell.setCellValue(value != null ? value.toString() : "");
                    }
                }
            }
            // 6. Auto-size columns for better readability
            for (int i = 0; i < firstRow.size(); i++) {
                sheet.autoSizeColumn(i);
            }
            // 7. Write the workbook to a file
            try (FileOutputStream fileOut = new FileOutputStream(excelFilePath)) {
                workbook.write(fileOut);
            }
            // 8. Close the workbook
            workbook.close();
            System.out.println("Excel file created successfully: " + excelFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Explanation:

  1. We read the data.json file.
  2. Jackson's objectMapper parses the JSON into a List<Map<String, Object>>. This is flexible because we don't need to create a Java class for the JSON structure.
  3. We create a new .xlsx workbook using XSSFWorkbook.
  4. We create the header row by getting the keys from the first map in our list.
  5. We iterate through the list of maps and create a new row for each one, populating the cells with the values.
  6. We handle different Java data types (String, Integer, Double, etc.) to ensure they are written correctly to Excel.
  7. sheet.autoSizeColumn() adjusts the column widths to fit the content.
  8. Finally, we write the workbook to output.xlsx and close all resources.

Scenario 2: Handling Nested JSON

Real-world JSON is often more complex. Let's consider a case with nested objects and arrays.

Java如何将JSON数据转换为Excel文件?-图3
(图片来源网络,侵删)

complex_data.json

[
  {
    "employeeId": "E001",
    "name": "Alice Wonderland",
    "contact": {
      "email": "alice@example.com",
      "phone": "123-456-7890"
    },
    "skills": ["Java", "Spring Boot", "SQL"],
    "projects": [
      { "name": "Project Alpha", "role": "Lead Developer" },
      { "name": "Project Beta", "role": "Architect" }
    ]
  },
  {
    "employeeId": "E002",
    "name": "Bob The Builder",
    "contact": {
      "email": "bob@example.com",
      "phone": "987-654-3210"
    },
    "skills": ["C#", ".NET", "Azure"],
    "projects": [
      { "name": "Project Gamma", "role": "Developer" }
    ]
  }
]

Writing this to a single sheet requires a strategy to flatten the data. A common approach is to use dot notation for nested keys and join array elements.

Here is a more advanced converter that handles this.

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class AdvancedJsonToExcelConverter {
    public static void main(String[] args) {
        String jsonFilePath = "complex_data.json";
        String excelFilePath = "complex_output.xlsx";
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            List<Map<String, Object>> jsonData = objectMapper.readValue(new File(jsonFilePath), new TypeReference<List<Map<String, Object>>>() {});
            // 1. Flatten the JSON data
            List<Map<String, String>> flattenedData = new ArrayList<>();
            for (Map<String, Object> employee : jsonData) {
                Map<String, String> flatEmployee = flattenJsonMap(employee);
                flattenedData.add(flatEmployee);
            }
            // 2. Create Excel Workbook and Sheet
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("Employees");
            // 3. Create Header Row
            Row headerRow = sheet.createRow(0);
            List<String> headers = new ArrayList<>(flattenedData.get(0).keySet());
            for (int i = 0; i < headers.size(); i++) {
                headerRow.createCell(i).setCellValue(headers.get(i));
            }
            // 4. Create Data Rows
            int rowIndex = 1;
            for (Map<String, String> rowData : flattenedData) {
                Row row = sheet.createRow(rowIndex++);
                for (int i = 0; i < headers.size(); i++) {
                    String value = rowData.get(headers.get(i));
                    row.createCell(i).setCellValue(value != null ? value : "");
                }
            }
            // 5. Auto-size columns
            for (int i = 0; i < headers.size(); i++) {
                sheet.autoSizeColumn(i);
            }
            // 6. Write to file
            try (FileOutputStream fileOut = new FileOutputStream(excelFilePath)) {
                workbook.write(fileOut);
            }
            workbook.close();
            System.out.println("Complex Excel file created successfully: " + excelFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * Recursively flattens a JSON map.
     * - Nested objects are flattened using dot notation (e.g., contact.email).
     * - Arrays are joined into a single string.
     */
    private static Map<String, String> flattenJsonMap(Map<String, Object> map) {
        Map<String, String> flattenedMap = new java.util.LinkedHashMap<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                // Recursively flatten nested maps
                Map<String, String> nested = flattenJsonMap((Map<String, Object>) value);
                for (Map.Entry<String, String> nestedEntry : nested.entrySet()) {
                    flattenedMap.put(key + "." + nestedEntry.getKey(), nestedEntry.getValue());
                }
            } else if (value instanceof List) {
                // Join lists into a comma-separated string
                List<?> list = (List<?>) value;
                String joinedString = String.join(", ", list.stream().map(Object::toString).toArray(String[]::new));
                flattenedMap.put(key, joinedString);
            } else {
                // Simple value
                flattenedMap.put(key, value != null ? value.toString() : "");
            }
        }
        return flattenedMap;
    }
}

Explanation of Changes:

  1. flattenJsonMap Method: This is the core of the advanced solution. It recursively processes the map:
    • If a value is another Map, it calls itself and prefixes the keys (e.g., contact becomes contact.email).
    • If a value is a List, it joins all elements into a single string separated by commas.
    • Otherwise, it stores the value as a string.
  2. Main Logic: The main method now first calls flattenJsonMap for each item in the JSON list to transform the complex structure into a simple Map<String, String>.
  3. Writing to Excel: The rest of the logic remains the same, but it now works with the flattened, simpler data structure.

Alternative: Using a Pre-defined Java Class (POJO)

If your JSON structure is fixed and known, it's often better to create a Plain Old Java Object (POJO) that matches the JSON structure. This provides type safety and cleaner code.

  1. Create the POJO(s)

    // Employee.java
    public class Employee {
        private String employeeId;
        private String name;
        private Contact contact;
        private List<String> skills;
        private List<Project> projects;
        // Getters and Setters (omitted for brevity)
    }
    // Contact.java
    public class Contact {
        private String email;
        private String phone;
        // Getters and Setters
    }
    // Project.java
    public class Project {
        private String name;
        private String role;
        // Getters and Setters
    }
  2. Modify the Conversion Code

    // In your main method
    List<Employee> employees = objectMapper.readValue(new File("complex_data.json"), new TypeReference<List<Employee>>() {});
    // Then you can access fields directly, e.g., employee.getContact().getEmail()
    // The writing logic would be similar but would use the POJO fields.

This approach is more maintainable for complex applications but requires more upfront boilerplate code.

分享:
扫描分享到社交APP
上一篇
下一篇