基于Java+Camel+Jackson将CSV转换为指定格式JSON的指导请求
Hey there! Let's walk through how to convert your CSV data into that specific JSON format using your tech stack. I'll cover the core approach, key code snippets, and how to tie it all together with Camel.
1. Core Approach Overview
The process breaks down into three main steps:
- Parse the CSV file (using Camel's built-in CSV component to handle header rows and data rows)
- Transform each CSV row into the target tag-based JSON structure (including converting the timestamp to ISO format)
- Serialize the transformed data to JSON with Jackson (we'll cover both POJO-based and manual JsonObject/JsonArray building, since you're learning the latter)
2. Step 1: Configure Camel to Parse CSV
Camel's csv component simplifies parsing by automatically mapping header rows to keys in a Map<String, Object> for each data row. Here's a basic route setup:
from("file:path/to/your/csv/files?noop=true") .unmarshal().csv() .setHeader(Exchange.CSV_USE_HEADER, constant(true)) .setHeader(Exchange.CSV_DELIMITER, constant(',')) // Pass to our custom transformation processor .process(new CsvToJsonTransformProcessor()) // Output the final JSON file .to("file:path/to/output/json/files?fileName=converted-data.json");
3. Step 2: Transform CSV Data to Target JSON Structure
Let's cover two approaches here—one for clean, maintainable code (POJOs) and one for practicing manual JSON object building.
Option A: POJO-Based Transformation (Recommended for Production)
First, define POJOs that mirror your target JSON structure:
// Top-level container public class TagDataCollection { private List<TagData> tags; // Constructors, getters, and setters } // Individual tag entry public class TagData { private String tagId; private List<TagValue> data; // Constructors, getters, and setters } // Single data point for a tag public class TagValue { private String ts; private String v; private String q = "3"; // Default to match your example // Constructors, getters, and setters }
Then, create a Camel Processor to convert CSV rows to these POJOs:
public class CsvToJsonTransformProcessor implements Processor { private static final DateTimeFormatter INPUT_DATE_FORMAT = DateTimeFormatter.ofPattern("M/d/yyyy h:mm:ss a"); private static final DateTimeFormatter OUTPUT_DATE_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME; @Override public void process(Exchange exchange) throws Exception { List<Map<String, Object>> csvRows = exchange.getIn().getBody(List.class); TagDataCollection collection = new TagDataCollection(); List<TagData> tags = new ArrayList<>(); for (Map<String, Object> row : csvRows) { // Parse and reformat the timestamp String inputTs = row.get("timestamp").toString(); LocalDateTime parsedTs = LocalDateTime.parse(inputTs, INPUT_DATE_FORMAT); String formattedTs = OUTPUT_DATE_FORMAT.format(parsedTs); // Create a TagData entry for each column except timestamp for (Map.Entry<String, Object> entry : row.entrySet()) { String tagId = entry.getKey(); if ("timestamp".equals(tagId)) continue; TagValue value = new TagValue(); value.setTs(formattedTs); value.setV(entry.getValue().toString()); TagData tagData = new TagData(); tagData.setTagId(tagId); tagData.setData(List.of(value)); tags.add(tagData); } } collection.setTags(tags); exchange.getIn().setBody(collection); } }
Option B: Manual JsonObject/JsonArray Building (For Learning)
If you want to practice using Jackson's low-level JSON APIs, here's how to build the structure manually:
public class CsvToJsonManualProcessor implements Processor { private static final DateTimeFormatter INPUT_DATE_FORMAT = DateTimeFormatter.ofPattern("M/d/yyyy h:mm:ss a"); private static final DateTimeFormatter OUTPUT_DATE_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME; private final ObjectMapper objectMapper = new ObjectMapper(); @Override public void process(Exchange exchange) throws Exception { List<Map<String, Object>> csvRows = exchange.getIn().getBody(List.class); JsonObject root = objectMapper.createObjectNode(); JsonArray tagsArray = objectMapper.createArrayNode(); for (Map<String, Object> row : csvRows) { String inputTs = row.get("timestamp").toString(); LocalDateTime parsedTs = LocalDateTime.parse(inputTs, INPUT_DATE_FORMAT); String formattedTs = OUTPUT_DATE_FORMAT.format(parsedTs); for (Map.Entry<String, Object> entry : row.entrySet()) { String tagId = entry.getKey(); if ("timestamp".equals(tagId)) continue; // Build the data point JsonObject dataPoint = objectMapper.createObjectNode(); dataPoint.put("ts", formattedTs); dataPoint.put("v", entry.getValue().toString()); dataPoint.put("q", "3"); // Build the tag entry JsonObject tagEntry = objectMapper.createObjectNode(); tagEntry.put("tagId", tagId); tagEntry.set("data", objectMapper.createArrayNode().add(dataPoint)); tagsArray.add(tagEntry); } } root.set("tags", tagsArray); exchange.getIn().setBody(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)); } }
4. Step 3: Serialize to JSON with Jackson
For the POJO approach, Camel will automatically use Jackson to serialize the TagDataCollection if you have the Camel Jackson dependency in your project. Add this to your pom.xml (Maven):
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jackson</artifactId> <version>${camel.version}</version> </dependency>
5. Key Tips & Notes
- Date Formatting: Double-check the input date pattern matches your CSV's timestamp format (your example uses
M/d/yyyy h:mm:ss afor single-digit months/days). - Large Files: For huge CSVs, use Camel's streaming capabilities to avoid loading the entire file into memory.
- Validation: Add checks for null values or invalid data in CSV rows to prevent runtime errors.
- Reusability: Extract date conversion and tag-building logic into utility classes to keep your processor clean.
内容的提问来源于stack exchange,提问作者GLMills

