如何使用Gson将数据保存到JSON文件中?

31
在我的 Web 应用程序中,我成功地使用 MyBatis 在 HTML 表格中显示数据。现在我想将 MySQL 表格的记录保存到 JSON 文件中,并创建一个用户数组。我使用了 Gson,但问题是只有一条记录保存在文件中。谢谢。
这是 file.json 文件中的结果:
{"data":
 [
 {"id":2,"Name":"Mike"}
 ]
}

servlet.java

SqlSession session = MyBatisSqlSessionFactory.getSession();
List<User> users = session.selectList("dao.UserDao.findAll");
for (User u : users) {
    Gson gson = new Gson();
    try {
        JsonWriter  writer = new JsonWriter(new FileWriter("C:\\file.json"));
        writer.beginObject();
        writer.name("data");
        writer.beginArray();
        writer.beginObject();
        writer.name("id").value(t.getId());
        writer.name("name").value(t.getNom());
        writer.endObject();
        writer.endArray();
        writer.endObject();
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

session.close();

因为你在每个循环迭代中都向同一个文件写入内容。你需要将_list_写入文件,而不是每个元素。 - Boris the Spider
如果我理解正确的话,我会将"JsonWriter writer=new JsonWriter(new FileWriter("C:\file.json"));"这一行代码放在for循环之前,但结果仍然相同。 - mak_doni
那你还没有理解。你需要编写 list!Gson 可以自行将其序列化为 JSON。 - Boris the Spider
我是初学者,这是我第一个使用JSON的例子。 - mak_doni
gson.toJsonTree用于去除斜杠。 - TechDog
3个回答

76

你把所有用户都写在同一个文件C:\\file.json中,所以只有循环的最后一次迭代被保存。

你可以将对象List<User>转换为json,并只写入一次(不需要循环)。

例子:

try (Writer writer = new FileWriter("Output.json")) {
    Gson gson = new GsonBuilder().create();
    gson.toJson(users, writer);
}

2
谢谢回答,我在JSON文件中有所有的用户,但为什么字符串需要反斜杠呢?我不需要反斜杠。"[ {"id":1,"name":"Nancy"}, {"id":2,"detail":"Mike"} ]" - mak_doni
如果您将其保存为完整对象而不更改字符串,则可以轻松将其转换回对象,但这取决于您的任务。 - Roy Shmuli
你有没有关于我的第一个建议使用循环的解决方案? - mak_doni
使用不同的文件名或创建一个要保存的对象(如List<user>),并将其保存为原样。 - Roy Shmuli
11
请记得在此之后调用writer.close(),否则结果文件将为空。 - Line
如果您不想使用斜杠,请使用gson.toJsonTree。 - TechDog

5
我之前使用outputStream.writeObject和Serializable以及默认的writer/reader来保存对象数据。由于代码可持续性存在问题,我一直在寻找其他方案。这就是结果。必须使用BufferedWriter,否则写入速度会下降8倍。请注意UTF-8声明,它是Json的默认编码。不确定不声明是否安全。
示例:
private void saveJson(Object object, Type type, String directory, String fileName) {

    File file = new File(getApplicationContext().getDir(directory, Context.MODE_PRIVATE),
            fileName);
    OutputStream outputStream = null;
    Gson gson = new GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting()
            .create();
    try {
        outputStream = new FileOutputStream(file);
        BufferedWriter bufferedWriter;
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,
                    StandardCharsets.UTF_8));
        } else {
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
        }

        gson.toJson(object, type, bufferedWriter);
        bufferedWriter.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
        if (DEBUG) Log.e(saveJson, "saveUserData, FileNotFoundException e: '" + e + "'");
    } catch (IOException e) {
        e.printStackTrace();
        if (DEBUG) Log.e(saveJson, "saveUserData, IOException e: '" + e + "'");
    } finally {
        if (outputStream != null) {
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                if (DEBUG) Log.e(saveJson, "saveUserData, finally, e: '" + e + "'");
            }
        }
    }

}


private Object loadJson(Type type,  String directory, String fileName) {
    Object jsonData = null;

    File file = new File(getApplicationContext().getDir(directory, Context.MODE_PRIVATE),
            fileName);
    InputStream inputStream = null;
    Gson gson = new GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting()
            .create();
    try {
        inputStream = new FileInputStream(file);
        InputStreamReader streamReader;
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            streamReader = new InputStreamReader(inputStream,
                    StandardCharsets.UTF_8);
        } else {
            streamReader = new InputStreamReader(inputStream, "UTF-8");
        }

        jsonData = gson.fromJson(streamReader, type);
        streamReader.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
        if (DEBUG) Log.e(TAG, "loadJson, FileNotFoundException e: '" + e + "'");
    } catch (IOException e) {
        e.printStackTrace();
        if (DEBUG) Log.e(TAG, "loadJson, IOException e: '" + e + "'");
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                if (DEBUG) Log.e(TAG, "loadJson, finally, e: '" + e + "'");
            }
        }
    }
    return jsonData;
}

例如,类型为:

Type type = new TypeToken<Map<String, Object>>() { }.getType();

2

您的代码的快速修复:

SqlSession session = MyBatisSqlSessionFactory.getSession();
List<User> users = session.selectList("dao.UserDao.findAll");
try {
    JsonWriter writer = new JsonWriter(new FileWriter("C:\\file.json"));
    writer.beginObject();
    writer.name("data");
    writer.beginArray();
    for (User u : users) {
        writer.beginObject();
        writer.name("id").value(t.getId());
        writer.name("name").value(t.getNom());
        writer.endObject();
    }
    writer.endArray();
    writer.endObject();
    writer.close();
} catch (IOException e) {
    e.printStackTrace();
}

然而,如果您的User类看起来像这样:
public class User {
    String id;
    String name;
}

那么您不需要编写适配器,因为Gson可以自动生成仅包含原始类型(int、String等)的类的JSON代码。因此,您的代码将与@roy-shmuli一样,但只有在省略数据并仅保留数组时才能完全生成List而无需适配器。生成的JSON代码如下所示:
[
    {"id":1, "name": "Mike"},
    {"id":2, "name": "Lucy"}
]

希望这对初学者有所帮助。


1
你有没有关于每次如何将数据附加到这个JSON文件的想法? - NarendraR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接