Appending JSONObjects when writing to a file

CoffeeBreak :

I'm trying to append JSONObjects inside a JSONArray that is called Records .

The first time I save it it saves it this way that is ok

{
  "Records": [
    {
      "travelTime": 2,
      "totalDistance": 0,
      "pace": 0,
      "kCalBurned": 0,
      "latlng": "[lat\/lng: (-32.1521234,-63.66412321)]"
    }
  ]
}

But when I try to append again a new jsonobject inside Records, it creates a new JSONArray for it, and I just want to append a new object inside records

{
  "Records": [
    {
      "travelTime": 2,
      "totalDistance": 0,
      "pace": 0,
      "kCalBurned": 0,
      "latlng": "[lat\/lng: (-31.6432292,-63.3667462)]"
    }
  ]
}{
  "Records": [
    {
      "travelTime": 1,
      "totalDistance": 0,
      "pace": 0,
      "kCalBurned": 0,
      "latlng": "[lat\/lng: (-31.9522431,-64.3461241)]"
    }
  ]
}

This is the code I use to save the Records

   private void writeJsonData(long travelTime,float totalDistance, float pace, float kCalBurned, LinkedList<LatLng> latlng){

        String jsonStr = "";
        JSONObject records  = new JSONObject();
        try {
            records.put("travelTime", travelTime);
            records.put("totalDistance", totalDistance);
            records.put("pace", pace);
            records.put("kCalBurned", kCalBurned);
            records.put("latlng", latlng);

            JSONArray jsonArray = new JSONArray();
            jsonArray.put(records);

            JSONObject recordsObj = new JSONObject();
            recordsObj.put("Records", jsonArray);

            jsonStr = recordsObj.toString();

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        String file_name = "records.json";

        FileOutputStream fileOutputStream = null;
        try {

            fileOutputStream = new FileOutputStream(new File(mContext.getFilesDir(),file_name),true);
            fileOutputStream.write(jsonStr.getBytes());
            fileOutputStream.close();


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


    }
Ali Ahsan :

Passing 2nd parameter to true in FileOutputStream constructor will append jsonObject at the end of file.

To append it with JSON array inside Records object, you've to read the file first, append the new JSON object and write it back to file.

Use GSON library for conversion between java class & jSON. So you don't have to create JSON object manually each time by putting each key-pair.

Create a Java class to hold whole Records object

public class Record
{
    @SerializedName("Records")
    private List<Object> recordsList;

    public Record()
    {
        this. recordsList = new ArrayList<>();
    }

    public List<Object> getRecordsList()
    {
        return recordsList;
    }
}

Now create JAVA Model class to hold travel info

public class Travel {

    private Integer travelTime;
    private Integer totalDistance;
    private Integer pace;
    private Integer kCalBurned;
    private LinkedList<LatLng> latlng;

    public Integer getTravelTime() {
        return travelTime;
    }

    public void setTravelTime(Integer travelTime) {
        this.travelTime = travelTime;
    }

    public Integer getTotalDistance() {
        return totalDistance;
    }

    public void setTotalDistance(Integer totalDistance) {
        this.totalDistance = totalDistance;
    }

    public Integer getPace() {
        return pace;
    }

    public void setPace(Integer pace) {
        this.pace = pace;
    }

    public Integer getKCalBurned() {
        return kCalBurned;
    }

    public void setKCalBurned(Integer kCalBurned) {
        this.kCalBurned = kCalBurned;
    }

    public LinkedList<LatLng> getLatlng() {
        return latlng;
    }

    public void setLatlng(LinkedList<LatLng> latlng) {
        this.latlng = latlng;
    }

}

Here is utility class with a function to append new JSON inside Records object. It will check if directory & file are created otherwise will create both.If file exist, it will read the file, append the new JSON object to list and write it back into the same file. You can change the directory & file name with yours.

Note: This class is written in Kotlin. Here is reference how to setup Android Studio for Kotlin

class Logger {

    companion object {

        private const val LOG_FILE_FOLDER = "Logs"
        private const val LOG_FILE_NAME = "transaction"
        private const val DATE_FORMAT = "yyyy-MM-dd"
        private val logFileName: String
            @SuppressLint("SimpleDateFormat")
            get() {

                var fileName = LOG_FILE_NAME
                val dateFormat = SimpleDateFormat(DATE_FORMAT)
                fileName += "_" + dateFormat.format(Date()) + ".json"
                return fileName
            }

fun logFile(json: Any) {

try {
    val directoryPath = Environment.getExternalStorageDirectory().path + "/" + LOG_FILE_FOLDER
    val loggingDirectoryPath = File(directoryPath)
    var loggingFile = File("$directoryPath/$logFileName")
    if (loggingDirectoryPath.mkdirs() || loggingDirectoryPath.isDirectory) {
        var isFileReady = true
        var isNewFile = false
        if (!loggingFile.exists()) {
            isFileReady = false
            try {
                loggingFile.createNewFile()
                isNewFile = true
                isFileReady = true
            } catch (e: Exception) {
                e.printStackTrace()
            }

        } else {
            val lastFile = getLastFile(loggingFile.name, directoryPath)
            loggingFile = File("$directoryPath/$lastFile")
            val fileSize = getFileSize(loggingFile)

        }
        if (isFileReady) {

            var jsonString: String? = null

            if (!isNewFile) {

                //Get already stored JsonObject
                val stream = FileInputStream(loggingFile)


                try {
                    val fileChannel = stream.channel
                    val mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size())

                    jsonString = Charset.defaultCharset().decode(mappedByteBuffer).toString()
                } catch (e: Exception) {
                    e.printStackTrace()
                } finally {
                    stream.close()
                }
            }


            //Create record object
            val record = if (!jsonString.isNullOrEmpty()) {
                Gson().fromJson(jsonString, Record::class.java)
            } else {
                Record()
            }


            //Append the current json
            record.recordList.add(json)

            //create json to save
            val jsonToSave = Gson().toJson(record)

            val bufferedOutputStream: BufferedOutputStream
            try {
                bufferedOutputStream = BufferedOutputStream(FileOutputStream(loggingFile))
                bufferedOutputStream.write(jsonToSave.toByteArray())
                bufferedOutputStream.flush()
                bufferedOutputStream.close()

            } catch (e4: FileNotFoundException) {
                e4.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            } finally {
                System.gc()
            }
        }
    }
} catch (ex: Exception) {
    ex.printStackTrace()
}
}
}
}

At the end, you can log the file withlogFile method

Logger.Companion.logFile(travel);

Cheers :)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=96678&siteId=1