Java中比较CSV数据、验证并返回JSON的最优实现方案
Got it, let's break down how to build this feature from start to finish. I'll walk you through each step with practical code examples that fit your exact CSV structure requirements.
First, we need classes that mirror the data in your two CSV files. This makes parsing and working with the data straightforward.
// For the first CSV (Car-Model mapping) public class CarModelMapping { private String carBrand; private String model; // Constructor, getters, setters (you can use Lombok to skip writing these manually!) public CarModelMapping(String carBrand, String model) { this.carBrand = carBrand; this.model = model; } // Add getters and setters here in your actual code } // For the second CSV (Model details) public class ModelDetail { private String model; private int bhp; private String fuelType; public ModelDetail(String model, int bhp, String fuelType) { this.model = model; this.bhp = bhp; this.fuelType = fuelType; } // Add getters and setters here too }
We'll use OpenCSV for parsing—it's lightweight and handles CSV edge cases (like whitespace or special characters) well. First, add the dependency to your Maven pom.xml (or adjust for Gradle):
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> <!-- Use the latest stable version available --> </dependency>
Now write utility methods to read each CSV into easy-to-use collections:
import com.opencsv.CSVReader; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class CsvReaderUtility { // Read first CSV into a map: car brand -> list of its models (for quick lookup) public static Map<String, List<String>> getCarToModelsMap(String csvPath) throws Exception { Map<String, List<String>> carModelsMap = new HashMap<>(); try (CSVReader reader = new CSVReader(new FileReader(csvPath))) { reader.readNext(); // Skip the header row String[] nextLine; while ((nextLine = reader.readNext()) != null) { String carBrand = nextLine[0].trim(); String model = nextLine[1].trim(); carModelsMap.computeIfAbsent(carBrand, k -> new ArrayList<>()).add(model); } } return carModelsMap; } // Read second CSV into a map: model -> its details (for quick lookup) public static Map<String, ModelDetail> getModelDetailsMap(String csvPath) throws Exception { Map<String, ModelDetail> modelDetailsMap = new HashMap<>(); try (CSVReader reader = new CSVReader(new FileReader(csvPath))) { reader.readNext(); // Skip header row String[] nextLine; while ((nextLine = reader.readNext()) != null) { String model = nextLine[0].trim(); int bhp = Integer.parseInt(nextLine[1].trim()); String fuelType = nextLine[2].trim(); modelDetailsMap.put(model, new ModelDetail(model, bhp, fuelType)); } } return modelDetailsMap; } }
Next, create a service class that takes user input, compares it against the CSV data, and generates a validation result. First, define classes for user input and the JSON response:
// User input request (could come from an API endpoint or console) public class ValidationRequest { private String carBrand; private String model; private Integer inputBhp; // Optional: if user wants to verify BHP private String inputFuelType; // Optional: if user wants to verify fuel type // Getters and setters here } // Validation result that will be converted to JSON public class ValidationResponse { private boolean isValid; private String message; private ModelDetail modelDetail; // Include details if validation passes public ValidationResponse(boolean isValid, String message, ModelDetail modelDetail) { this.isValid = isValid; this.message = message; this.modelDetail = modelDetail; } // Getters and setters here }
Now the core validation service:
public class ValidationService { private final Map<String, List<String>> carModelsMap; private final Map<String, ModelDetail> modelDetailsMap; // Load CSV data once at app startup (don't reload on every request!) public ValidationService(String carCsvPath, String modelDetailCsvPath) throws Exception { this.carModelsMap = CsvReaderUtility.getCarToModelsMap(carCsvPath); this.modelDetailsMap = CsvReaderUtility.getModelDetailsMap(modelDetailCsvPath); } public ValidationResponse validateInput(ValidationRequest request) { // Step 1: Check if the car brand exists in our data if (!carModelsMap.containsKey(request.getCarBrand())) { return new ValidationResponse(false, "Car brand '" + request.getCarBrand() + "' is not found.", null); } // Step 2: Check if the model is associated with the given brand List<String> modelsForBrand = carModelsMap.get(request.getCarBrand()); if (!modelsForBrand.contains(request.getModel())) { return new ValidationResponse(false, "Model '" + request.getModel() + "' doesn't belong to brand '" + request.getCarBrand() + "'.", null); } // Step 3: Validate optional input fields against model details ModelDetail detail = modelDetailsMap.get(request.getModel()); if (request.getInputBhp() != null && request.getInputBhp() != detail.getBhp()) { return new ValidationResponse(false, "Input BHP doesn't match. Expected: " + detail.getBhp(), detail); } if (request.getInputFuelType() != null && !request.getInputFuelType().equalsIgnoreCase(detail.getFuelType())) { return new ValidationResponse(false, "Input Fuel Type doesn't match. Expected: " + detail.getFuelType(), detail); } // All checks passed! return new ValidationResponse(true, "Validation successful.", detail); } }
We'll use Jackson to serialize the ValidationResponse to JSON. Add the Jackson dependency:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- Use the latest stable version --> </dependency>
Here's how to use it in a main class or API endpoint:
import com.fasterxml.jackson.databind.ObjectMapper; public class Main { public static void main(String[] args) { try { // Load CSV data once (do this at app startup, not per request!) ValidationService service = new ValidationService("path/to/car-models.csv", "path/to/model-details.csv"); // Example user input ValidationRequest request = new ValidationRequest(); request.setCarBrand("Toyota"); request.setModel("Corolla"); request.setInputBhp(150); // Run validation ValidationResponse response = service.validateInput(request); // Convert to pretty-printed JSON ObjectMapper objectMapper = new ObjectMapper(); String jsonResponse = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(response); System.out.println(jsonResponse); } catch (Exception e) { e.printStackTrace(); } } }
For a valid input, you'll get:
{ "isValid" : true, "message" : "Validation successful.", "modelDetail" : { "model" : "Corolla", "bhp" : 150, "fuelType" : "Diesel" } }
If the input BHP was incorrect:
{ "isValid" : false, "message" : "Input BHP doesn't match. Expected: 150", "modelDetail" : { "model" : "Corolla", "bhp" : 150, "fuelType" : "Diesel" } }
内容的提问来源于stack exchange,提问作者colmulhall

