【问题标题】:Cannot convert Json file to Vector or HashTable or HashMap.... org.json无法将 Json 文件转换为 Vector 或 HashTable 或 HashMap.... org.json
【发布时间】:2020-02-09 00:03:33
【问题描述】:

我已经为此花费了几天时间。我查看了来自其他有类似问题的人的一百万个不同的帖子,并尝试了很多不同的东西,但我无法将我的 json 文件读入我的程序。

这是一个学校作业。该演示适用于一个媒体库,它读取示例 music.json 文件并在 JTree 中显示曲目。我们的第一个任务是将通用媒体库转换为特定音乐库,添加 Track 和 Album 类,并在通过应用搜索​​专辑和艺术家时从 last.fm 获取搜索结果,并将结果显示在 JTree 中。

我设法创建了专辑和曲目类,读取 last.fm json 并将其转换为专辑对象。然后我将该 Album 对象重写为一个新的 album.json 文件。从那以后,我开始着手将该 json 文件读回 MusicLibrary 类,以便它可以在 JTree 中显示结果。那就是我遇到麻烦的地方。我必须进行一些转换,因为给定的 music.json 是为了按曲目进行组织(在没有专辑类之前),现在我需要它来处理新的专辑类(其中包含曲目对象的向量)。

我不能使用任何需要 maven 或下载的 jar 才能工作的工具(所以没有 GSON 等)。我只能使用 org.json 方法。讲师的原始代码将 music.json 读入 HashTable。我已经尝试将它读入其中,读入 Vector 和 HashMap。没有任何效果。我不断收到错误:

Exception reading music library album.json: JSONObject["channel"] is not a JSONObject. 或者 Exception reading music library album.json: JSONObject["album"] is not a JSONObject.

或者没有错误,但是当我尝试打印表格/地图/矢量时,它总是空的。第一个错误是当我不使用 JSONTokener 并使用它下面的注释行时。我不知道它在哪里提出了“频道”。这在我的代码中没有。无论如何,我在下面发布我的相关代码。如果您看到大量注释掉的行,那么这些都是我尝试过的不同的东西和/或一些讲师的原始代码(例如 HashTable 库)。

album.json(我将其放入格式化程序和验证程序以便更好地显示)

{
  "album": "Believe",
  "albumTracks": [
    {
      "trackInfo": "Track Name: Believe\nArtist: Cher\nRank: 1\nDuration: 241\n\n",
      "trackArtist": "Cher",
      "trackRank": "1",
      "trackDuration": "241",
      "trackTitle": "Believe"
    },
    {
      "trackInfo": "Track Name: The Power\nArtist: Cher\nRank: 2\nDuration: 236\n\n",
      "trackArtist": "Cher",
      "trackRank": "2",
      "trackDuration": "236",
      "trackTitle": "The Power"
    },
    {
      "trackInfo": "Track Name: Runaway\nArtist: Cher\nRank: 3\nDuration: 286\n\n",
      "trackArtist": "Cher",
      "trackRank": "3",
      "trackDuration": "286",
      "trackTitle": "Runaway"
    },
    {
      "trackInfo": "Track Name: All or Nothing\nArtist: Cher\nRank: 4\nDuration: 237\n\n",
      "trackArtist": "Cher",
      "trackRank": "4",
      "trackDuration": "237",
      "trackTitle": "All or Nothing"
    },
    {
      "trackInfo": "Track Name: Strong Enough\nArtist: Cher\nRank: 5\nDuration: 223\n\n",
      "trackArtist": "Cher",
      "trackRank": "5",
      "trackDuration": "223",
      "trackTitle": "Strong Enough"
    },
    {
      "trackInfo": "Track Name: Dov'e L'amore\nArtist: Cher\nRank: 6\nDuration: 258\n\n",
      "trackArtist": "Cher",
      "trackRank": "6",
      "trackDuration": "258",
      "trackTitle": "Dov'e L'amore"
    },
    {
      "trackInfo": "Track Name: Takin' Back My Heart\nArtist: Cher\nRank: 7\nDuration: 272\n\n",
      "trackArtist": "Cher",
      "trackRank": "7",
      "trackDuration": "272",
      "trackTitle": "Takin' Back My Heart"
    },
    {
      "trackInfo": "Track Name: Taxi Taxi\nArtist: Cher\nRank: 8\nDuration: 304\n\n",
      "trackArtist": "Cher",
      "trackRank": "8",
      "trackDuration": "304",
      "trackTitle": "Taxi Taxi"
    },
    {
      "trackInfo": "Track Name: Love Is the Groove\nArtist: Cher\nRank: 9\nDuration: 271\n\n",
      "trackArtist": "Cher",
      "trackRank": "9",
      "trackDuration": "271",
      "trackTitle": "Love Is the Groove"
    },
    {
      "trackInfo": "Track Name: We All Sleep Alone\nArtist: Cher\nRank: 10\nDuration: 233\n\n",
      "trackArtist": "Cher",
      "trackRank": "10",
      "trackDuration": "233",
      "trackTitle": "We All Sleep Alone"
    }
  ],
  "albumArtist": "Cher",
  "albumSummary": "Believe is the twenty-third studio album by American  singer-actress Cher, released on November 10, 1998 by Warner Bros. Records. The RIAA certified it Quadruple Platinum on December 23, 1999, recognizing four million shipments in the United States; Worldwide, the album has sold more than 20 million copies, making it the biggest-selling album of her career. In 1999 the album received three Grammy Awards nominations including \"Record of the Year\", \"Best Pop Album\" and winning \"Best Dance Recording\" for the single \"Believe\". <a href=\"http://www.last.fm/music/Cher/Believe\">Read more on Last.fm</a>.",
  "albumImage": "https://lastfm.freetls.fastly.net/i/u/174s/b0c2311a9af7f0edbc8b99450944ca1b.png"
}

我的 Album.java 类,因此您可以看到我如何将 Album 对象写入 Json,以防出现问题。

    /**
     * Converts the Album object along with its associated Track objects to a JSONObject toString
     * 
     * @return Returns the Album/Track objects as a JSONObject toString
     */
    public String toJString() {
        String jString = "{}";
        try {
            jString = this.albumToJObject().toString(0);
        } catch (Exception ex) {
            System.out.println("Exception in Album toJString: " + ex.getMessage());
        }
        return jString;
    }

    /**
     * Converts the Track object to a JSONObject.
     * 
     * @return Returns the Track object as a JSONObject.
     */
    public JSONObject albumToJObject() {
        JSONObject jObject = new JSONObject();
        try {
            jObject.put("album", albumName);
            jObject.put("albumArtist", albumArtist);
            jObject.put("albumImage", albumImage);
            jObject.put("albumSummary", albumSummary);
            jObject.put("albumTracks", (Object)albumTracks);

            // System.out.println("Full Album JSONObject: " + jObject.toString());

        } catch (Exception ex) {
            System.out.println("Exception in Album toJObject: " + ex.getMessage());
        }
        return jObject;
    }

    public void writeAlbumToJson() {
        try {
            Writer output = null;
            File file = new File("album.json");
            output = new BufferedWriter(new FileWriter(file));
            output.write(this.albumToJObject().toString());
            output.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in writeAlbumToJson: " + ex.getMessage());
        }
    }

这是 MusicLibrary 类声明和构造函数,为了清楚我当前的代码是什么而进行了清理:

public class MusicLibrary extends Object implements Serializable {

    private Map<String, Album> musicLib;
    private static final String mFileName = "album.json";

    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));
            }
            JSONObject music = new JSONObject(new JSONTokener(inputStream));
            Iterator<String> iter = music.keys();

            while(iter.hasNext()) {
                String key = iter.next();
                JSONObject jAlbumObj = music.optJSONObject(key);
                if (music.get(key) instanceof JSONObject) {
                    Album album = new Album(jAlbumObj);
                    musicLib.put(key, 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());
        }
    }

【问题讨论】:

  • 首先,阅读您正在使用的类的 Javadocs; VectorHashtable 已经过时了 20 年(改用 ListMap)。您还需要精简代码以找到会导致错误的最小版本;这里有太多东西让我们整理。这样做,您很可能会发现具体的不匹配。
  • 我知道 Vector 和 Hashtable 已过时,但由于某种原因,讲师同时使用了这两种方法。我确实在我的专辑类中为曲目尝试了 Vector 和 ArrayList,最后让它与 Vector 一起使用。在 MusicLibrary 课程中,我切换到了 Map(讲师使用了 HT,我将他的声明留在了那里,但我没有在任何地方使用它)。最大的问题是在 MusicLibrary 构造函数中,将 json 文件放入 Map。我添加了额外的注释代码以显示我尝试过的其他内容。
  • 我刚刚发布了清理后的 MusicLibrary.java 类
  • 有人对此有任何想法吗?我最好的猜测实际上是 Json 文件本身有问题。我觉得我读取的 Json 代码是正确的,因为它与此回复 stackoverflow.com/a/4149555/9576364 和许多其他人匹配(除了我的地图是 而不是 .

标签: java json collections


【解决方案1】:

根据您的解释,我了解到MusicLibrary 应该读取album.json 文件并将其转换为地图Map&lt;String, Album&gt; musicLib;,其中关键是专辑名称。

您没有提供整个 AlbumTrack 类,但我会假设它们具有接受 JSONObject 参数的构造函数。

您的错误是您尝试遍历JSONObjectiter.next() 将始终只返回 Object,而不是您想要的 JSONObject。另外,考虑到您提供的album.json 只有一张专辑,根本没有必要进行迭代(除非album.json 应该有多个专辑)。

另外,我认为 json 结构(键名)是已知的,因此您可以使用这些名称来提取数据。请看下面的代码:

public class MusicLibrary{

    private Map<String, Album> musicLib;
    private static final String mFileName = "album.json";

    public MusicLibrary() {
        this.musicLib = new HashMap<>();
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream(this.mFileName);
            if (inputStream == null) {
                inputStream = new FileInputStream(new File(this.mFileName));
            }

            JSONObject jAlbum = new JSONObject(new JSONTokener(inputStream));
            Album album = new Album(jAlbum);
            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());
        }
    }


}

public class Album {

    private String albumName;
    private String albumArtist;
    private String albumImage;
    private String albumSummary;
    private List<Track> albumTracks = new LinkedList<>();

    public Album(JSONObject obj) {
        albumName = obj.getString("album");
        albumArtist = obj.getString("albumArtist");
        albumImage = obj.getString("albumImage");
        albumSummary = obj.getString("albumSummary");
        JSONArray tracks = obj.getJSONArray("albumTracks");

        for (int i = 0; i < tracks.length(); i++) {
            albumTracks.add(new Track(tracks.getJSONObject(i)));
        }
    }

    public String getAlbumName() {
        return albumName;
    }


    @Override
    public String toString() {
        return "Album{" +
                "albumName='" + albumName + '\'' +
                ", albumArtist='" + albumArtist + '\'' +
                ", albumImage='" + albumImage + '\'' +
                ", albumSummary='" + albumSummary + '\'' +
                ", albumTracks=" + albumTracks +
                '}';
    }
}

public class Track {
    private String trackInfo;
    private String trackArtist;
    private String trackRank;
    private String trackDuration;
    private String trackTitle;

    public Track(JSONObject obj) {
        trackInfo = obj.getString("trackInfo");
        trackArtist = obj.getString("trackArtist");
        trackRank = obj.getString("trackRank");
        trackDuration = obj.getString("trackDuration");
        trackTitle = obj.getString("trackTitle");
    }
    @Override
    public String toString() {
        return "Track{" +
                "trackInfo='" + trackInfo + '\'' +
                ", trackArtist='" + trackArtist + '\'' +
                ", trackRank='" + trackRank + '\'' +
                ", trackDuration='" + trackDuration + '\'' +
                ", trackTitle='" + trackTitle + '\'' +
                '}';
    }
}

最后,考虑从MusicLibrary 构造函数中删除逻辑和文件读取,不要显式扩展Object,也不要实现Serializable,除非你真的知道自己在做什么。

【讨论】:

  • 感谢您的详细回复。我最初的目标是拥有它,以便最终album.json 的格式将替换music.json 的格式,并且它可以读取多个专辑以填充库(并保留)。另外,我必须按照讲师的说明扩展 Object 并实现 Serializable。无论如何,我被告知我把它弄得太复杂了,我唯一的目标是在 JTree 中显示新的搜索结果,所以我以一种不接受新的 .json 文件的方式进行处理,而是取而代之直接将 Album 对象添加到 Map/
  • 我会尝试你的建议,但一旦我得到这种迂回的方式工作,因为这种新方式不会持久化我的数据。
猜你喜欢
  • 2010-10-02
  • 2011-08-24
  • 2018-07-17
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 2014-12-13
  • 2019-11-24
  • 2012-04-19
相关资源
最近更新 更多