如何从Spotify API返回的JSON响应中提取duration_ms和explicit字段
问题根因
你猜测的原因是正确的,问题确实出在items是数组类型,不能直接跳过数组下标定位内部字段:
- 第一次Jackson写法的
/tracks/items/duration_ms路径是非法的,数组必须指定下标才能定位到具体的对象元素,比如定位第一首曲目的时长应该写/tracks/items/0/duration_ms,否则无法匹配到对应节点,返回的durationNode实际是空节点。 - 后续调整的org.json版本已经解决了路径问题,但存在逻辑缺陷:循环内直接覆盖
duration_ms和explicit变量,最终只会保留数组最后一个曲目的对应值,如果你需要提取所有返回曲目的信息,需要用集合存储每首歌的字段。
完整实现方案
下面的实现会提取你需要的所有字段:艺术家列表、曲目名称、时长、是否为explicit内容,返回所有匹配曲目信息的集合。
org.json版本(你当前使用的依赖)
import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public static List<Map<String, Object>> filterMetadata(String metadata) throws IOException { List<Map<String, Object>> trackInfoList = new ArrayList<>(); JSONObject rootJson = new JSONObject(metadata); JSONObject tracks = rootJson.getJSONObject("tracks"); JSONArray items = tracks.getJSONArray("items"); for (int i = 0; i < items.length(); i++) { JSONObject currentTrack = items.getJSONObject(i); Map<String, Object> trackInfo = new HashMap<>(); // 提取曲目名 trackInfo.put("track_name", currentTrack.getString("name")); // 提取艺术家列表 JSONArray artists = currentTrack.getJSONArray("artists"); List<String> artistNames = new ArrayList<>(); for (int j = 0; j < artists.length(); j++) { artistNames.add(artists.getJSONObject(j).getString("name")); } trackInfo.put("artists", artistNames); // 提取时长 trackInfo.put("duration_ms", currentTrack.getInt("duration_ms")); // 提取explicit标记 trackInfo.put("explicit", currentTrack.getBoolean("explicit")); trackInfoList.add(trackInfo); } return trackInfoList; }
Jackson版本(你第一次使用的依赖)
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public static List<Map<String, Object>> filterMetadata(String metadata) throws IOException { List<Map<String, Object>> trackInfoList = new ArrayList<>(); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(metadata); JsonNode itemsNode = rootNode.at("/tracks/items"); if (itemsNode.isArray()) { for (JsonNode currentTrack : itemsNode) { Map<String, Object> trackInfo = new HashMap<>(); // 提取曲目名 trackInfo.put("track_name", currentTrack.get("name").asText()); // 提取艺术家列表 List<String> artistNames = new ArrayList<>(); currentTrack.get("artists").forEach(artist -> artistNames.add(artist.get("name").asText())); trackInfo.put("artists", artistNames); // 提取时长 trackInfo.put("duration_ms", currentTrack.get("duration_ms").asInt()); // 提取explicit标记 trackInfo.put("explicit", currentTrack.get("explicit").asBoolean()); trackInfoList.add(trackInfo); } } return trackInfoList; }
补充说明
如果你只需要提取某一首特定曲目的信息,不需要循环,直接指定数组下标即可,比如取第一首曲目信息的代码为items.getJSONObject(0)(org.json版本),或者路径写为/tracks/items/0/目标字段(Jackson版本)。
内容的提问来源于stack exchange,提问作者DDHD
相关产品推荐
相关产品推荐

