Gson将JSON保存到磁盘并加载回内存

时间:2019-02-28 11:29:18

标签: android json caching gson

我将JSONObject保存到磁盘,然后当我尝试将其加载回JSONObject时,在loadSavedScheduleFromDisk方法的这一行出现以下异常:

JSONObject jsonObject = gson.fromJson(reader, JSONObject.class);

com.google.gson.JsonSyntaxException:com.google.gson.stream.MalformedJsonException:第1行第74040列的未终止字符串路径$ .nameValuePairs..values [32] .values [2] .nameValuePairs.disciplineVersionId

这是我的代码:

private void loadSavedScheduleFromDisk(Activity act) {
    try {
        File file = new File(((Context)act).getCacheDir()+"/"+SCHED_CACHE_FILENAME);

        Gson gson = new Gson();
        InputStreamReader freader = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
        JsonReader reader = new JsonReader(freader);//new FileReader(file));
        reader.setLenient(true);
        JSONObject jsonObject = gson.fromJson(reader, JSONObject.class);
        parseSchedule(jsonObject);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void saveScheduleToDisk(Activity act, JSONObject jsonObject )
{
    try {
        File file = new File(((Context)act).getCacheDir()+"/"+SCHED_CACHE_FILENAME);

        //Writer writer = new FileWriter(file);
        Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8"));
        Gson gson = new GsonBuilder().create();
        gson.toJson(jsonObject, writer);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

这是非常对称的,我不明白为什么它不起作用-我想如果我使用API​​将我的JSONObject保存到磁盘上并且保存成功,那我怎么不能再加载相同的数据呢? / p>

1 个答案:

答案 0 :(得分:1)

我认为问题在于您没有关闭WRITER或默认适配器更改了数据

该错误表明您的JSON严重关闭,可能您的对象未正确压缩或字符串转义不正确

这是我的主张,我的考验通过了我

我创建JSONFileUtil并使用AutoCloseable如果需要关闭流,则最佳实践是使用try-with-resources语句link

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;

public class JSONFileUtil {

    public void save(File file, MyDTO myDto) {
        try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8"))) {
            writer.write(new Gson().toJson(myDto));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public MyDTO load(File file) {
        try (InputStreamReader freader = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"))) {
            JsonReader reader = new JsonReader(freader);
            return new Gson().fromJson(reader, MyDTO.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

和MyDTO

import java.util.Date;

public class MyDTO {

    public String valueString;
    public Long valueLong;
    public Date valueDate;
}

和我的测试

import java.io.File;
import java.util.Date;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

public class JSONFileUtilTest {

    @Test
    public void saveAndLoad() {
        //given:
        MyDTO myDTO = new MyDTO();
        myDTO.valueString = "aaa";
        myDTO.valueLong = 4L;
        myDTO.valueDate = new Date(1551427491625L);
        File cacheFile = new File("cache" + File.separator + "name.json");
        //when:
        JSONFileUtil jsonFileUtil = new JSONFileUtil();
        jsonFileUtil.save(cacheFile, myDTO);
        MyDTO resultMyDto = jsonFileUtil.load(cacheFile);
        //then:
        assertEquals(myDTO.valueLong, resultMyDto.valueLong);  //4
        assertEquals(myDTO.valueString, resultMyDto.valueString);  // "aaa"
        assertEquals(myDTO.valueDate.toString(), resultMyDto.valueDate.toString());  // "Mar 1, 2019 9:04:51 AM" OK
        assertNotEquals(myDTO.valueDate.getTime(), resultMyDto.valueDate.getTime()); // it not 1551427491625L but 1551427491000L --> 1551427491625L because the default date format does not store milliseconds 
        //to store this you need to write your adapter

    }
}