如何解析任意类型JSON并提取其中的字符串值?
提取复杂JSON中的所有字符串值
嘿,我看你需要解析任意结构的JSON(不管是对象还是嵌套数组),只提取其中所有的字符串值对吧?结合你已经写了一部分的UrlActions类,我给你完善两种可行的Java实现方案,不管JSON结构多复杂都能轻松提取:
方案一:用Jackson库(推荐,处理复杂结构更高效)
Jackson是Java生态中处理JSON最常用的库之一,它的流式API可以逐Token遍历JSON,不需要提前定义实体类,完美适配任意JSON结构。
1. 先添加Maven依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 建议使用最新稳定版 --> </dependency>
2. 完整实现代码
我把你的readAll方法补全,再加上核心的JSON解析逻辑:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.util.ArrayList; import java.util.List; public class UrlActions { private static String readAll(Reader rd) throws IOException { StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } return sb.toString(); } // 从指定URL获取JSON并提取所有字符串值 public static List<String> extractAllStringsFromJsonUrl(String urlStr) throws IOException { URL url = new URL(urlStr); try (InputStreamReader reader = new InputStreamReader(url.openStream())) { String jsonContent = readAll(reader); return extractAllStringsFromJson(jsonContent); } } // 解析JSON字符串,提取所有字符串值 public static List<String> extractAllStringsFromJson(String jsonContent) throws IOException { List<String> stringValues = new ArrayList<>(); ObjectMapper objectMapper = new ObjectMapper(); try (JsonParser parser = objectMapper.getFactory().createParser(jsonContent)) { JsonToken token; while ((token = parser.nextToken()) != null) { // 只要遇到字符串类型的Token,就把值加入列表 if (token == JsonToken.VALUE_STRING) { stringValues.add(parser.getText()); } // 其他类型(对象、数组、数字等)会自动遍历子元素,无需手动递归 } } return stringValues; } // 测试示例:调用你提供的Yahoo财经JSON链接 public static void main(String[] args) { try { String jsonUrl = "https://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json"; List<String> strings = extractAllStringsFromJsonUrl(jsonUrl); System.out.println("提取到的所有字符串值:"); strings.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } }
代码说明
readAll:你已经写了核心逻辑,我补全了返回值,用来把输入流的内容转为完整的JSON字符串。extractAllStringsFromJsonUrl:负责从指定URL获取JSON流,转交给解析方法。extractAllStringsFromJson:核心逻辑,用Jackson的流式解析器逐Token遍历,不管JSON嵌套多少层,只要是字符串就提取,完全适配任意结构。
方案二:用org.json库(轻量,适合简单场景)
如果你不想引入Jackson这样的大库,也可以用轻量的org.json库,通过递归遍历JSON对象和数组来提取字符串:
1. 添加Maven依赖
<dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20230618</version> </dependency>
2. 完整实现代码
import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; public class UrlActions { private static String readAll(Reader rd) throws IOException { StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } return sb.toString(); } public static List<String> extractAllStringsFromJsonUrl(String urlStr) throws IOException { URL url = new URL(urlStr); try (InputStreamReader reader = new InputStreamReader(url.openStream())) { String jsonContent = readAll(reader); // 先判断根节点是对象还是数组 Object jsonRoot; if (jsonContent.trim().startsWith("[")) { jsonRoot = new JSONArray(jsonContent); } else { jsonRoot = new JSONObject(jsonContent); } return extractAllStrings(jsonRoot); } } // 递归遍历JSON结构,提取所有字符串 private static List<String> extractAllStrings(Object json) { List<String> stringValues = new ArrayList<>(); if (json instanceof JSONObject) { JSONObject jsonObj = (JSONObject) json; // 遍历JSON对象的所有键值对 for (Map.Entry<String, Object> entry : jsonObj.toMap().entrySet()) { Object value = entry.getValue(); if (value instanceof String) { stringValues.add((String) value); } else { // 非字符串类型,递归处理 stringValues.addAll(extractAllStrings(value)); } } } else if (json instanceof JSONArray) { JSONArray jsonArray = (JSONArray) json; // 遍历JSON数组的所有元素 for (int i = 0; i < jsonArray.length(); i++) { Object element = jsonArray.get(i); if (element instanceof String) { stringValues.add((String) element); } else { // 非字符串元素,递归处理 stringValues.addAll(extractAllStrings(element)); } } } // 数字、布尔、null等类型直接忽略 return stringValues; } // 测试示例 public static void main(String[] args) { try { String jsonUrl = "https://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json"; List<String> strings = extractAllStringsFromJsonUrl(jsonUrl); System.out.println("提取到的所有字符串值:"); strings.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } } }
代码说明
这个方案通过递归遍历JSON的每个节点,判断节点类型:如果是字符串就加入列表,如果是对象或数组就继续递归,直到所有字符串都被提取。
内容的提问来源于stack exchange,提问作者Adeel Faisal
相关产品推荐
相关产品推荐

