0

I'm saving my JSONObject to disk and then when I try to load it back to JSONObject, I get the following exception on this line of the loadSavedScheduleFromDisk method:

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

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated string at line 1 column 74040 path $.nameValuePairs..values[32].values[2].nameValuePairs.disciplineVersionId

Here is my code:

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();
    }
}

It is quite symmetrical and I can't understand why it doesn't work - I think if I use API to save my JSONObject to disk and it saves OK, then how come I can't load same data back?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Ivan
  • 6,388
  • 3
  • 24
  • 30
  • 1
    A much more simpler option is saving it as a String on sharepreferences and then create the [Json from string](https://stackoverflow.com/a/5245881/4978313). – Tiago Ornelas Feb 28 '19 at 11:32
  • Does your `JSON` is valid? What you can find under this path: `$.nameValuePairs..values[32].values[2].nameValuePairs.disciplineVersionId`? – Michał Ziober Feb 28 '19 at 11:50
  • I believe my JSON is valid, cause I already have it as JSONObject in memory in the saveScheduleToDisk() method. I also load this JSON from server before saving to disk and all works fine. – Ivan Feb 28 '19 at 12:56
  • I did not try shared prefs cause I read somewhere that it is for saving small strings. In my case this JSON can be 800Kb and more, but I will give it a try if nothing helps – Ivan Feb 28 '19 at 13:03
  • @Ivan, this is very suspicious but could you check this path: `$.nameValuePairs..values[32].values[2].nameValuePairs.disciplineVersionId`? Maybe there is a some kind of special character? – Michał Ziober Feb 28 '19 at 14:50
  • 1
    @Michal I didn't find anything wrong with those values, I will post my solution here as soon as I solve this problem – Ivan Feb 28 '19 at 15:42

1 Answers1

1

I think the problem is that you do not close WRITER or the default adapter change your data

the error indicates that you have a badly closed JSON maybe your object has not been compressed correctly or String escape was incorrect

this is my proposition and my tests pass me

I create JSONFileUtil and I use AutoCloseable If you need to close a stream, then best practice would be to use the try-with-resources statement 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);
        }
    }

}

And MyDTO

import java.util.Date;

public class MyDTO {

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

and my test

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

    }
}
DEV-Jacol
  • 567
  • 3
  • 10
  • thanks for this answer! yes indeed, the problem was that I did not close the WRITER. After I did close it I stopped getting that exception. I did not try your code, but I can see that you are not closing the WRITER as well... – Ivan Mar 04 '19 at 12:33
  • @Ivan use AutoCloseable If you need to close a stream, then best practice would be to use the try-with-resources statement [link](https://stackoverflow.com/questions/13141302/implements-closeable-or-implements-autocloseable#answer-13141382) – DEV-Jacol Mar 04 '19 at 16:38