Java读取CSV转嵌套JSON的最简方案及可用Jar包咨询
Got it, let's break down how to convert CSV to nested JSON in Java—since you mentioned your CSV format can be flexible, we can leverage that to make the mapping straightforward. Below are two practical, minimal approaches using widely-used libraries that avoid the "flat JSON" issue you've encountered.
Approach 1: OpenCSV + Jackson
This combo uses OpenCSV for reliable CSV parsing and Jackson for JSON serialization. The key trick is structuring your CSV headers with dot notation (e.g., user.name, user.address.city) to define nested levels.
Step 1: Add Dependencies (Maven)
<!-- OpenCSV for reading CSV files --> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> </dependency> <!-- Jackson for converting nested maps to JSON --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
Step 2: Example CSV Structure
Format your CSV with headers that hint at nested structures:
id,user.name,user.address.city,user.address.zip,order.id,order.amount 1,John Doe,New York,10001,ORD001,99.99 2,Jane Smith,Los Angeles,90001,ORD002,149.99
Step 3: Code Implementation
import com.opencsv.CSVReader; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CsvToNestedJson { public static void main(String[] args) throws Exception { // Initialize CSV reader CSVReader csvReader = new CSVReader(new FileReader("your-file.csv")); String[] headers = csvReader.readNext(); String[] currentLine; List<Map<String, Object>> nestedJsonData = new ArrayList<>(); // Process each CSV row while ((currentLine = csvReader.readNext()) != null) { Map<String, Object> nestedMap = new HashMap<>(); for (int i = 0; i < headers.length; i++) { String[] nestedKeys = headers[i].split("\\."); Map<String, Object> currentLevel = nestedMap; // Build nested map structure for (int j = 0; j < nestedKeys.length - 1; j++) { currentLevel = (Map<String, Object>) currentLevel.computeIfAbsent(nestedKeys[j], k -> new HashMap<>()); } // Assign value to the final nested key currentLevel.put(nestedKeys[nestedKeys.length - 1], currentLine[i]); } nestedJsonData.add(nestedMap); } // Convert nested maps to pretty-printed JSON ObjectMapper objectMapper = new ObjectMapper(); String jsonOutput = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(nestedJsonData); System.out.println(jsonOutput); csvReader.close(); } }
Approach 2: Apache Commons CSV + Jackson
If you prefer Apache Commons CSV over OpenCSV, the logic is almost identical—just swap out the CSV parsing part.
Step 1: Add Dependencies (Maven)
<!-- Apache Commons CSV --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.10.0</version> </dependency> <!-- Jackson (same as before) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
Step 2: Code Implementation
import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CommonsCsvToNestedJson { public static void main(String[] args) throws Exception { // Parse CSV with headers CSVParser csvParser = CSVFormat.DEFAULT.withHeader().parse(new FileReader("your-file.csv")); List<Map<String, Object>> nestedJsonData = new ArrayList<>(); for (CSVRecord record : csvParser) { Map<String, Object> nestedMap = new HashMap<>(); for (String header : csvParser.getHeaderNames()) { String[] nestedKeys = header.split("\\."); Map<String, Object> currentLevel = nestedMap; for (int j = 0; j < nestedKeys.length - 1; j++) { currentLevel = (Map<String, Object>) currentLevel.computeIfAbsent(nestedKeys[j], k -> new HashMap<>()); } currentLevel.put(nestedKeys[nestedKeys.length - 1], record.get(header)); } nestedJsonData.add(nestedMap); } // Convert to JSON ObjectMapper objectMapper = new ObjectMapper(); String jsonOutput = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(nestedJsonData); System.out.println(jsonOutput); csvParser.close(); } }
Handling More Complex Nested Structures
If you need arrays (e.g., multiple phone numbers per user), adjust your CSV headers to use index notation like user.phones[0], user.phones[1]. You can modify the key-splitting logic to detect numeric indexes and create List objects instead of Maps for those levels.
For example, a CSV row like:
id,user.name,user.phones[0],user.phones[1] 3,Bob Brown,555-1234,555-5678
Can be mapped to a JSON object with a phones array by adding logic to check if a key segment is an integer.
内容的提问来源于stack exchange,提问作者Hari surya prakash Turangi

