Reputation: 6785
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();
}
}
Upvotes: 4
Views: 3796
Reputation: 995
Passing 2nd parameter to
true
inFileOutputStream
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 :)
Upvotes: 1
Reputation: 349
You need a JSON parser so that you can locate the "Records" array inside the file and place the new data there. I used the "json simple" library (jar can be found here: https://code.google.com/archive/p/json-simple/downloads).
First you parse the file:
JSONParser parser = new JSONParser();
JSONObject records = null;
try {
records = (JSONObject) parser.parse(new FileReader("records.json"));
} catch (ParseException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
Then you locate the Records JSONArray. In there you want to append the new record:
JSONArray r = (JSONArray) records.get("Records");
Create the new record:
JSONObject NewObj = new JSONObject();
NewObj.put("travelTime", travelTime);
NewObj.put("totalDistance", totalDistance);
NewObj.put("pace", pace);
NewObj.put("kCalBurned", kCalBurned);
NewObj.put("latlng", latlng);
Add the new record to the "Records" JSONArray:
r.add(NewObj);
Write to file:
try (FileWriter file = new FileWriter("records.json")) {
file.write(records.toJSONString());
} catch (IOException ex) {
ex.printStackTrace();
}
Upvotes: 3