Java中JSON数据提取与处理的完整指南
引言
在开发中,JSON数据的处理已经成为日常任务。无论是与前端交互、调用第三方API,还是处理数据库中的JSON字段,我们需要解析和提取JSON数据。
1. 基础JSON数组解析
场景描述
处理简单的JSON数组字符串,将其转换为Java集合。
示例JSON
["苹果", "香蕉", "橙子", ""]
处理方法
public List<String> parseSimpleJsonArray(String jsonArrayStr) {
List<String> resultList = new ArrayList<>();
// 第一步:严格的空值检查
if (jsonArrayStr == null || jsonArrayStr.trim().isEmpty()) {
return resultList; // 返回空集合而不是null
}
try {
// 第二步:JSON解析
JSONArray jsonArray = JSONArray.parseArray(jsonArrayStr);
// 第三步:遍历和数据处理
for (int i = 0; i < jsonArray.size(); i++) {
String item = jsonArray.getString(i);
// 第四步:数据验证和清理
if (item != null && !item.trim().isEmpty()) {
resultList.add(item.trim());
}
}
} catch (Exception e) {
// 第五步:异常处理
log.error("解析简单JSON数组失败,原始数据: {}", jsonArrayStr, e);
// 根据业务需求决定是否抛出异常或返回空列表
}
return resultList;
}
关键要点
-
防御性编程:始终进行null检查和空字符串检查
-
数据清理:使用trim()去除空白字符
-
异常恢复:在catch块中提供合理的默认返回值
2. 对象数组的特定字段提取
场景描述
从包含多个对象的JSON数组中提取特定字段的值。
示例JSON
[
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"age": 25
},
{
"id": 2,
"username": "jane_smith",
"email": "jane@example.com",
"age": 30
}
]
处理方法
public List<String> extractSpecificFields(String jsonArrayStr, String... fieldNames) {
List<String> extractedValues = new ArrayList<>();
if (jsonArrayStr == null || jsonArrayStr.trim().isEmpty()) {
return extractedValues;
}
try {
JSONArray jsonArray = JSONArray.parseArray(jsonArrayStr);
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
// 提取指定的多个字段
for (String fieldName : fieldNames) {
if (jsonObject.containsKey(fieldName)) {
String value = jsonObject.getString(fieldName);
if (value != null && !value.trim().isEmpty()) {
extractedValues.add(value.trim());
}
}
}
}
} catch (Exception e) {
log.error("提取字段失败,字段: {}, 数据: {}",
Arrays.toString(fieldNames), jsonArrayStr, e);
}
return extractedValues;
}
// 使用示例
List<String> emails = extractSpecificFields(userJson, "email");
List<String> namesAndEmails = extractSpecificFields(userJson, "username", "email");
关键要点
-
灵活性:通过可变参数支持多个字段的提取
-
键存在性检查:使用containsKey()避免MissingKey异常
-
批量处理:一次遍历处理多个字段,提高效率
3. 通用对象值提取方法
场景描述
提取JSON数组中所有对象的所有值,适用于不确定数据结构的情况。
示例JSON
[
{
"firstName": "张",
"lastName": "三",
"department": "技术部"
},
{
"employeeId": "E1002",
"position": "工程师",
"level": "P7"
}
]
处理方法
public List<String> extractAllValuesFromObjects(String jsonArrayStr) {
List<String> allValues = new ArrayList<>();
if (jsonArrayStr == null || jsonArrayStr.trim().isEmpty()) {
return allValues;
}
try {
JSONArray jsonArray = JSONArray.parseArray(jsonArrayStr);
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
// 遍历对象的所有键
for (String key : jsonObject.keySet()) {
try {
// 尝试以字符串形式获取值
String value = jsonObject.getString(key);
if (value != null && !value.trim().isEmpty()) {
allValues.add(value.trim());
}
} catch (Exception e) {
// 处理非字符串值的情况
Object obj = jsonObject.get(key);
if (obj != null) {
allValues.add(obj.toString());
}
}
}
}
} catch (Exception e) {
log.error("提取所有值失败,数据: {}", jsonArrayStr, e);
}
return allValues;
}
关键要点
-
通用性:处理各种数据类型的值
-
错误隔离:单个键值提取失败不影响其他值的处理
-
类型安全:正确处理非字符串类型的值
4. 复杂嵌套结构处理
场景描述
处理多层嵌套的JSON结构,提取深层次的数据。
示例JSON
{
"company": {
"name": "某科技有限公司",
"departments": [
{
"name": "研发部",
"employees": [
{
"id": 101,
"personalInfo": {
"name": "李四",
"contact": {
"email": "lisi@company.com",
"phone": "13800138000"
}
}
}
]
}
]
}
}
处理方法
public List<String> extractFromNestedStructure(String complexJson) {
List<String> results = new ArrayList<>();
if (complexJson == null || complexJson.trim().isEmpty()) {
return results;
}
try {
JSONObject root = JSONObject.parseObject(complexJson);
// 安全地访问嵌套属性
JSONObject company = root.getJSONObject("company");
if (company != null) {
// 提取公司名称
String companyName = company.getString("name");
addIfNotEmpty(results, companyName);
// 处理部门数组
JSONArray departments = company.getJSONArray("departments");
if (departments != null) {
for (int i = 0; i < departments.size(); i++) {
JSONObject dept = departments.getJSONObject(i);
processDepartment(dept, results);
}
}
}
} catch (Exception e) {
log.error("解析嵌套JSON结构失败", e);
}
return results;
}
private void processDepartment(JSONObject department, List<String> results) {
String deptName = department.getString("name");
addIfNotEmpty(results, deptName);
JSONArray employees = department.getJSONArray("employees");
if (employees != null) {
for (int i = 0; i < employees.size(); i++) {
JSONObject employee = employees.getJSONObject(i);
processEmployee(employee, results);
}
}
}
private void processEmployee(JSONObject employee, List<String> results) {
JSONObject personalInfo = employee.getJSONObject("personalInfo");
if (personalInfo != null) {
String name = personalInfo.getString("name");
addIfNotEmpty(results, name);
JSONObject contact = personalInfo.getJSONObject("contact");
if (contact != null) {
String email = contact.getString("email");
String phone = contact.getString("phone");
addIfNotEmpty(results, email);
addIfNotEmpty(results, phone);
}
}
}
private void addIfNotEmpty(List<String> list, String value) {
if (value != null && !value.trim().isEmpty()) {
list.add(value.trim());
}
}
关键要点
-
模块化:将复杂逻辑分解为小方法
-
安全访问:逐层检查JSONObject是否为null
-
关注点分离:每个方法只负责一个层级的处理
5. 高级技巧和最佳实践(AI)
5.1 使用Optional避免空指针
public Optional<List<String>> safeJsonExtraction(String jsonStr) {
return Optional.ofNullable(jsonStr)
.filter(str -> !str.trim().isEmpty())
.map(str -> {
try {
return JSONArray.parseArray(str);
} catch (Exception e) {
log.warn("JSON解析警告", e);
return null;
}
})
.map(this::extractValuesSafely)
.orElse(Optional.empty());
}
5.2 性能优化-批量处理
public <T> List<T> batchProcessJson(List<String> jsonList,
Function<String, List<T>> processor) {
return jsonList.parallelStream()
.map(processor)
.flatMap(List::stream)
.collect(Collectors.toList());
}
5.3 自定义异常处理
public class JsonProcessingException extends RuntimeException {
private final String originalJson;
public JsonProcessingException(String message, String originalJson, Throwable cause) {
super(message, cause);
this.originalJson = originalJson;
}
// 提供更友好的错误信息
public String getUserMessage() {
return "数据处理失败,请检查数据格式";
}
}
6. 完整的工具类示例
@Slf4j
public class JsonExtractionUtils {
private JsonExtractionUtils() {
// 工具类,防止实例化
}
/**
* 通用JSON数组值提取器
*/
public static List<String> extractValues(String jsonArrayStr,
ValueExtractor... extractors) {
List<String> results = new ArrayList<>();
if (!isValidJsonString(jsonArrayStr)) {
return results;
}
try {
JSONArray jsonArray = JSONArray.parseArray(jsonArrayStr);
for (int i = 0; i < jsonArray.size(); i++) {
Object item = jsonArray.get(i);
processJsonItem(item, extractors, results);
}
} catch (Exception e) {
handleJsonException("JSON数组解析失败", jsonArrayStr, e);
}
return results;
}
private static boolean isValidJsonString(String jsonStr) {
return jsonStr != null && !jsonStr.trim().isEmpty();
}
private static void processJsonItem(Object item,
ValueExtractor[] extractors,
List<String> results) {
if (item instanceof JSONObject) {
processJsonObject((JSONObject) item, extractors, results);
} else if (item instanceof String) {
processStringValue((String) item, results);
}
// 可以扩展处理其他类型
}
private static void processJsonObject(JSONObject jsonObject,
ValueExtractor[] extractors,
List<String> results) {
for (ValueExtractor extractor : extractors) {
try {
extractor.extract(jsonObject, results);
} catch (Exception e) {
log.warn("字段提取失败: {}", extractor.getFieldName(), e);
}
}
}
private static void processStringValue(String value, List<String> results) {
if (value != null && !value.trim().isEmpty()) {
results.add(value.trim());
}
}
private static void handleJsonException(String message,
String jsonStr,
Exception e) {
log.error("{}: {}", message, jsonStr, e);
// 根据环境决定是否抛出异常
if (isProduction()) {
throw new JsonProcessingException(message, jsonStr, e);
}
}
private static boolean isProduction() {
return "prod".equals(System.getProperty("app.env"));
}
@FunctionalInterface
public interface ValueExtractor {
void extract(JSONObject jsonObject, List<String> results);
default String getFieldName() { return "unknown"; }
}
}
总结
在处理JSON数据时,记住以下核心原则:
-
安全性优先:始终进行空值检查和异常处理
-
数据验证:验证提取数据的有效性和完整性
-
代码可读性:使用清晰的命名和模块化设计
-
性能考虑:对于大数据量考虑使用流式处理
-
可维护性:提供清晰的错误信息和日志记录
通过遵循这些模式和最佳实践,你可以构建出健壮、可维护的JSON处理代码,轻松应对各种复杂的数据提取场景。