
本文详细介绍了在java和android开发中如何高效地解析json数组(jsonarray),从中提取特定键对应的值,并在此基础上实现数据筛选。内容涵盖json对象的遍历、值获取、异常处理以及结合实际场景(如根据邮箱地址筛选经纬度信息)的代码实现,旨在提供一个结构清晰、易于理解的教程。
1. 理解JSON数据结构
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。在Java和Android开发中,我们经常需要处理来自服务器的JSON数据。
JSON数据主要有两种基本结构:
- JSON对象 (JSONObject):一个无序的“键/值”对集合。键是一个字符串,值可以是字符串、数字、布尔值、另一个JSON对象、JSON数组或null。在Java中通常对应 org.json.JSONObject 类。
- JSON数组 (JSONArray):一个有序的值集合。每个值可以是任何JSON数据类型(字符串、数字、布尔值、JSON对象、JSON数组等)。在Java中通常对应 org.json.JSONArray 类。
本教程将重点讲解如何处理包含多个JSON对象的 JSONArray。
2. 解析JSONArray并提取数据
假设我们有一个包含多个用户位置信息的 JSONArray,每个对象包含 num、email、lati(纬度)、longt(经度)和 time 等字段。我们的目标是解析这个数组,并提取 lati 和 longt 值。
立即学习“Java免费学习笔记(深入)”;
2.1 将JSON字符串转换为JSONArray对象
首先,你需要将接收到的JSON字符串转换为 JSONArray 对象。
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
public class JsonParserExample {
// 假设这是你从API获取到的JSON字符串
private static final String JSON_DATA = "[" +
" {" +
" \"num\": \"34304\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888888\"," +
" \"longt\": \"88888888\"," +
" \"time\": \"2022-12-08 21:15:39\"" +
" }," +
" {" +
" \"num\": \"34303\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34302\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34301\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34300\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }" +
"]";
public static void main(String[] args) {
try {
JSONArray jsonArray = new JSONArray(JSON_DATA);
System.out.println("成功将JSON字符串转换为JSONArray,包含 " + jsonArray.length() + " 个元素。");
} catch (JSONException e) {
e.printStackTrace();
System.err.println("JSON解析错误: " + e.getMessage());
}
}
}2.2 遍历JSONArray并获取JSONObject
JSONArray 实际上是一个 JSONObject 的列表。我们需要遍历这个数组,对每个 JSONObject 进行处理。
// 假设你已经有了JSONArray jsonArray
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonObject = jsonArray.getJSONObject(i); // 获取当前索引的JSONObject
// 或者更安全的做法:
// JSONObject jsonObject = jsonArray.optJSONObject(i);
// optJSONObject在索引越界或元素不是JSONObject时返回null,避免抛出JSONException
// 现在可以从jsonObject中提取值
String num = jsonObject.getString("num");
String email = jsonObject.getString("email");
String lati = jsonObject.getString("lati");
String longt = jsonObject.getString("longt");
String time = jsonObject.getString("time");
System.out.println("--- 元素 " + i + " ---");
System.out.println("Num: " + num);
System.out.println("Email (raw): " + email);
System.out.println("Lati: " + lati);
System.out.println("Longt: " + longt);
System.out.println("Time: " + time);
} catch (JSONException e) {
e.printStackTrace();
System.err.println("处理JSONArray中的元素时发生错误: " + e.getMessage());
}
}2.3 从JSONObject中提取特定值
JSONObject 提供了多种方法来获取不同类型的值:
- getString(String key): 获取字符串值。
- getInt(String key): 获取整数值。
- getDouble(String key): 获取双精度浮点数值。
- getBoolean(String key): 获取布尔值。
- getJSONObject(String key): 获取嵌套的JSONObject。
- getJSONArray(String key): 获取嵌套的JSONArray。
与 get 方法对应的,还有 opt 方法(如 optString、optInt 等)。opt 方法在键不存在时不会抛出 JSONException,而是返回一个默认值(例如 optString 返回空字符串,optInt 返回0,optJSONObject 返回null),这在处理可选字段时非常有用。
在我们的例子中,lati 和 longt 都是字符串类型,但我们通常需要将它们转换为 double 类型以表示地理坐标。
// ... 在上面的for循环内部 ...
String latiStr = jsonObject.getString("lati");
String longtStr = jsonObject.getString("longt");
try {
double latitude = Double.parseDouble(latiStr);
double longitude = Double.parseDouble(longtStr);
System.out.println("Parsed Lati: " + latitude + ", Parsed Longt: " + longitude);
// 可以在这里将latitude和longitude存储到自定义对象或列表中
} catch (NumberFormatException e) {
System.err.println("纬度或经度值格式错误: " + latiStr + ", " + longtStr);
}3. 应用筛选逻辑:根据Email筛选数据
原始问题要求根据特定的邮箱地址筛选数据。在我们的JSON数据中,email 字段是一个HTML 标签,其中包含了实际的邮箱地址。我们需要先从这个HTML标签中提取出纯文本的邮箱地址,然后再进行筛选。
3.1 提取纯文本Email地址
由于 email 字段是 [email protected] 这样的HTML结构,直接获取 getString("email") 会得到整个HTML字符串。我们需要从这个字符串中提取 [email protected]。一种简单的方法是使用正则表达式或字符串替换来移除HTML标签。
// 辅助方法:从HTML字符串中提取纯文本邮箱
private static String extractEmailFromHtml(String htmlEmail) {
// 移除所有HTML标签
String plainText = htmlEmail.replaceAll("<[^>]*>", "");
// 替换HTML实体 为普通空格
plainText = plainText.replace(" ", " ");
return plainText.trim();
}
// ... 在for循环内部,获取email字符串后 ...
String rawEmail = jsonObject.getString("email");
String cleanEmail = extractEmailFromHtml(rawEmail);
System.out.println("Cleaned Email: " + cleanEmail);
// 假设我们要筛选的邮箱是 "[email protected]"
String targetEmail = "[email protected]";
if (cleanEmail.equals(targetEmail)) {
// 匹配成功,提取经纬度
String latiStr = jsonObject.getString("lati");
String longtStr = jsonObject.getString("longt");
try {
double latitude = Double.parseDouble(latiStr);
double longitude = Double.parseDouble(longtStr);
System.out.println("--- 找到匹配邮箱的数据 ---");
System.out.println("Email: " + cleanEmail);
System.out.println("Lati: " + latitude);
System.out.println("Longt: " + longitude);
// 将匹配的经纬度添加到结果列表中
} catch (NumberFormatException e) {
System.err.println("筛选后纬度或经度值格式错误: " + latiStr + ", " + longtStr);
}
}4. 完整示例代码
结合上述所有步骤,下面是一个完整的Java代码示例,演示如何解析JSON数组,提取经纬度,并根据邮箱地址进行筛选。
为了更好地组织数据,我们定义一个简单的 LatLng 类来存储经纬度。
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// 模拟Android中的LatLng类
class LatLng {
public double latitude;
public double longitude;
public LatLng(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
@Override
public String toString() {
return "LatLng{" +
"latitude=" + latitude +
", longitude=" + longitude +
'}';
}
}
public class JsonDataProcessor {
private static final String JSON_DATA = "[" +
" {" +
" \"num\": \"34304\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888888\"," +
" \"longt\": \"88888888\"," +
" \"time\": \"2022-12-08 21:15:39\"" +
" }," +
" {" +
" \"num\": \"34303\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34302\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34301\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }," +
" {" +
" \"num\": \"34300\"," +
" \"email\": \"[email protected]\"," +
" \"lati\": \"8888\"," +
" \"longt\": \"88888\"," +
" \"time\": \"8888888\"" +
" }" +
"]";
/**
* 从HTML字符串中提取纯文本邮箱地址。
* 例如,从 "[email protected]" 提取 "[email protected]"
*
* @param htmlEmail 包含邮箱的HTML字符串
* @return 纯文本邮箱地址,如果无法提取则返回空字符串。
*/
private static String extractEmailFromHtml(String htmlEmail) {
// 使用正则表达式匹配标签内部的文本内容
// Pattern pattern = Pattern.compile("(?<=>)(.*?)(?=<)"); // 匹配标签内部所有内容
// 更精确地匹配 [email @] 格式
Pattern pattern = Pattern.compile("\\[email @\\][^\\]]*"); // 匹配 [email @] 后面的内容直到 ]
Matcher matcher = pattern.matcher(htmlEmail);
if (matcher.find()) {
String extracted = matcher.group(0);
// 替换HTML实体










