使用org.json读取album.json至MusicLibrary类时遇转换错误求助
Hey Krista, let's break down what's going wrong here and fix it step by step.
1. Why You're Seeing Those Errors
- The
JSONObject["channel"] is not a JSONObjecterror almost certainly means you accidentally loaded the raw last.fm API response (which has achannelroot field) instead of your customalbum.jsonfile at some point. Double-check that your input stream is pointing to the correct file. - The
JSONObject["album"] is not a JSONObjecterror and empty collection happen because youralbum.jsonis a single Album object, but yourMusicLibrarycode is treating it like a map of multiple albums. When you iterate over the keys of the root JSON object, keys like"album"point to a string ("Believe"), not another JSONObject—so your checkif (music.get(key) instanceof JSONObject)never passes, and nothing gets added tomusicLib.
2. Fix the Album Class (Add JSON Constructor)
First, you need a constructor in your Album class that can build an Album from a JSONObject, including parsing the albumTracks array into a Vector<Track>:
// Add this to your Album class public Album(JSONObject jAlbum) throws JSONException { this.albumName = jAlbum.getString("album"); this.albumArtist = jAlbum.getString("albumArtist"); this.albumImage = jAlbum.getString("albumImage"); this.albumSummary = jAlbum.getString("albumSummary"); // Parse albumTracks array into Vector<Track> JSONArray tracksArray = jAlbum.getJSONArray("albumTracks"); this.albumTracks = new Vector<>(); for (int i = 0; i < tracksArray.length(); i++) { JSONObject trackJson = tracksArray.getJSONObject(i); Track track = new Track( trackJson.getString("trackTitle"), trackJson.getString("trackArtist"), Integer.parseInt(trackJson.getString("trackRank")), Integer.parseInt(trackJson.getString("trackDuration")) ); // If your Track class has a constructor that takes JSONObject, use that instead this.albumTracks.add(track); } }
(Note: Adjust the Track constructor call to match your actual Track class implementation—if Track has its own JSON parsing constructor, use that instead of passing individual fields.)
3. Fix the MusicLibrary Constructor
Your current code is trying to iterate over a map of albums, but your album.json only contains one album. Update the constructor to directly parse the root JSONObject as an Album, then add it to your musicLib map:
public MusicLibrary() { this.musicLib = new HashMap<String, Album>(); try { InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(this.mFileName); if (inputStream == null) { inputStream = new FileInputStream(new File(this.mFileName)); } // Parse the entire JSON as a single Album object JSONObject albumJson = new JSONObject(new JSONTokener(inputStream)); Album album = new Album(albumJson); // Use album name as the key in the map (you could use another unique identifier if needed) musicLib.put(album.getAlbumName(), album); System.out.println("DEBUG: musicLib HashMap contents: " + musicLib.toString()); } catch (Exception ex) { ex.printStackTrace(); System.out.println("Exception reading music library " + mFileName + ": " + ex.getMessage()); } }
4. Verify the JSON Structure
Your existing album.json looks correct, but just to confirm: it's a single object with top-level fields like album, albumArtist, and albumTracks (an array of track objects). This matches the parsing logic we just added.
Quick Notes
- Make sure your
Trackclass has the necessary constructors or JSON parsing methods to build Track objects from the JSON track entries. - If you ever need to store multiple albums in
album.json, you'd need to wrap them in a JSON array or a top-level map (like{"albums": [{}, {}]}), but for now, the single album structure works with the fixed code.
内容的提问来源于stack exchange,提问作者Krista

