From my Android application I write a JSON string to a JSON-file located on an Android tablet in /sdcard/subdirectory, in the onStop()-method. This function executes succesfully.
If I copy this resulting .json-file from the Android device to my computer and I open this JSON-file in Notepad++, the JSON is not valid: it is incomplete.
This is the content of said JSON-file:
{... there are about 20 of these elements, I won't list them all for readability...},
{"name":"Marker7","long":2.924128,"lat":51.204594,"warning":"Sharp turn"},
{"name":"Marker8","long":2.9260479999999998,"lat":51.203364,"warning":"Dead end"},
{"name":"Marker9","long":2.926252,"lat":51.203209,"warning":"
As you can see, the JSON is cut off at the warning part of Marker9, making this invalid JSON.
What is weird is the following: my application also reads from this file in the onCreate()-method, and if I print this JSON, it does show the correct and complete JSON! So within my Android app I don't experience any issues, and I assume my writing method and the resulting JSON-file is working as intended since the correct data is retrieved from the reading-function. However if I want to copy this JSON and use it elsewhere I won't have a valid JSON-file.
Why is this? Does this have something to do with the ext4-filesystem that my Android device is using?
I also noticed that this seems to happen when the file reaches the 1.18kB size mark (as shown in my explorer view, but again: the correct and complete IS retrieved within the Android app...), because each time I copy the file and it appears to be cut off, the size is always exactly 1.18kB.
Update
The code for reading the JSON:
public String loadJSON() {
String json = null;
try {
//InputStream is = getAssets().open("markers.json");
File jsonFile = new File(Environment.getExternalStorageDirectory(), "osmdroid/markers.json");
FileInputStream is = new FileInputStream(jsonFile);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
private void readJsonMarkers() throws JSONException {
JSONObject obj = new JSONObject(loadJSON());
JSONArray jsonArray = obj.getJSONArray("markers");
System.out.println("JSON LOAD: " + jsonArray); // this shows the correct, full list of markers
}
The code for writing the JSON:
private void writeJsonMarkers() throws JSONException {
JSONArray data = new JSONArray();
for(OverlayItem oi: waypointMarkers){
JSONObject obj = new JSONObject();
try {
obj.put("name", oi.getTitle());
obj.put("long", oi.getPoint().getLongitude());
obj.put("lat", oi.getPoint().getLatitude());
obj.put("warning", oi.getSnippet());
data.put(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
JSONObject rootObj = new JSONObject(loadJSON());
rootObj.remove("markers");
rootObj.put("markers",data);
// this method is used to remove the existing markers-list from the JSON, and add an updated markers-list to it
File jsonFile = new File(Environment.getExternalStorageDirectory(), "osmdroid/markers.json");
try {
FileWriter jsonWriter = new FileWriter(jsonFile);
jsonWriter.write(rootObj.toString());
jsonWriter.flush();
jsonWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Related
I've been trying to develop an application that returns the first video result for a keyword (as well as getting its content details). This is done multiple times in a session (let's say, like 30 times). If all I'm doing is reading data from 1 result each time (from the "Calculating quota usage" section of their docs), then why is it that I use up all 10,000 of my daily units with a few test runs of my application?
Here's my specific code:
private class GetVideoDuration extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String sURL = "https://www.googleapis.com/youtube/v3/videos?id=" + params[0] + "&part=contentDetails&key=" + API_KEY;
String var = null;
try {
// Connect to the URL using java's native library
URL url = new URL(sURL);
URLConnection request = url.openConnection();
request.connect();
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
Log.d("rootJSON", root.toString());
Log.d("urlJSON", url.toString());
JsonObject video = null;
try {
video = root.getAsJsonObject().get("items").getAsJsonArray().get(0).getAsJsonObject().get("contentDetails").getAsJsonObject();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
Log.e("Chief", "It looks like we've exceeded our quota for the day :(");
}
var = video.get("duration").getAsString();
} catch (IOException e) {
e.printStackTrace();
// contDets = contentDetails
Log.d("Error parsing contDets", e.getMessage());
ERROR_STATE = true;
}
return var;
}
}
I'm aware of the option to apply for a higher quota, but it just seems like something's wrong. Any help would be greatly appreciated.
The problem is that I cannot open a .json file from the /assets folder.
The function I used:
The call:
String json = readJSONFile("planner.json");
I mention that the Activity extends Fragment.
THE ERROR:
the is = manager.open(fileName); is null
Am I missing something?
EDIT:
Logs:
Which comes from:
It's normal, due to the fact that the manager.open(fileName) returns null;
Try below code
JSONObject obj = new JSONObject(readJSONFromAsset("planner.json"));
public String readJSONFromAsset(String fileName) {
String json = null;
try {
InputStream is = getActivity().getAssets().open(fileName);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
Updated
You making a asset folder in wrong way in wrong path make it proper and it will work
I get my JSON response properly encoded with UTF-8 and I try to save the string of response into my SQLite table.
Then I noticed that it is not properly saved and has ????? characters when not english.
I tried to fix encoding before saving
#Override
public void onResponse(String response)
{
SavedResponse mysavedresponse = new SavedResponse();
JSONObject j = null;
int resp_count = (int) db.getResponsesCount();
try {
//String MyResponse = fixEncodingUnicode(response);
//CHECK IF IT IS NEW RESPONSE
if(resp_count>0)
{
mysavedresponse = db.getMySavedResponse();
response = mysavedresponse.getSavedresponse();
}else
{
**db.AddResponse(fixEncodingUnicode(response));**
db.close();
}
j = new JSONObject(response);
}catch (JSONException e) {
e.printStackTrace();
}
Additionally, If I add db.deleteresponses initialy then its working if I comment out the db.deleteresponses I get again ??????.
Why if my response is properly encoded I can see it on debug, it is messed up when it is saved in sqlite table?
thank you
Does your JSON object need to be stored exactly as JSON in SQLite? It would be easier to just base64 encode it, since you don't have to worry about character set clashes then with all the characters encoded in ASCII.
I am generating Observation objects and want to add them to a json file. The way I'm doing it now, I'm parsing existing file and converting it to JSON object, then adding a new Observation instance to the retrieved collection, parsing it back to JSON and re-writing the file.
Here's my code:
final File file = getFile();
final ObservationSet observationSet = retrievePreviousObservations(file);
observationSet.getObservations().add(observation[0]);
final OutputStream os = new FileOutputStream(file);
os.write(GsonHelper.toJson(observationSet).getBytes());
os.close();
...
private ObservationSet retrievePreviousObservations(final File file) {
ObservationSet observationSet = new ObservationSet();
try {
final BufferedReader br = new BufferedReader(new FileReader(file));
observationSet = GsonHelper.getGson().fromJson(br, ObservationSet.class);
} catch (FileNotFoundException e) {
Log.w(TAG, "No previous file found, this is the first entry", e);
}
return observationSet;
}
The problem is, that the Observation objects are quite big and after several tens of entries, this appending process takes really long time (generally more than 10 seconds for 20+ items in the collection).
Is there a way to append to existing JSON file without having to parse the existing one, adding the object, parsing it back and rewriting the file?
Hi there i'm creating my first android app and i'm wanting to know what is the best and most efficient way of parsing a JSON Feed from a URL.Also Ideally i want to store it somewhere so i can keep going back to it in different parts of the app. I have looked everywhere and found lots of different ways of doing it and i'm not sure which to go for. In your opinion whats the best way of parsing json efficiently and easily?
I'd side with whatsthebeef on this one, grab the data and then serialize to disk.
The code below shows the first stage, grabbing and parsing your JSON into a JSON Object and saving to disk
// Create a new HTTP Client
DefaultHttpClient defaultClient = new DefaultHttpClient();
// Setup the get request
HttpGet httpGetRequest = new HttpGet("http://example.json");
// Execute the request in the client
HttpResponse httpResponse = defaultClient.execute(httpGetRequest);
// Grab the response
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
// Instantiate a JSON object from the request response
JSONObject jsonObject = new JSONObject(json);
// Save the JSONOvject
ObjectOutput out = new ObjectOutputStream(new FileOutputStream(new File(getCacheDir(),"")+"cacheFile.srl"));
out.writeObject( jsonObject );
out.close();
Once you have the JSONObject serialized and save to disk, you can load it back in any time using:
// Load in an object
ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(new File(getCacheDir(),"")+"cacheFile.srl")));
JSONObject jsonObject = (JSONObject) in.readObject();
in.close();
Your best bet is probably GSON
It's simple, very fast, easy to serialize and deserialize between json objects and POJO, customizable, although generally it's not necessary and it is set to appear in the ADK soon. In the meantime you can just import it into your app. There are other libraries out there but this is almost certainly the best place to start for someone new to android and json processing and for that matter just about everyone else.
If you want to persist you data so you don't have to download it every time you need it, you can deserialize your json into a java object (using GSON) and use ORMLite to simply push your objects into a sqlite database. Alternatively you can save your json objects to a file (perhaps in the cache directory)and then use GSON as the ORM.
This is pretty straightforward example using a listview to display the data. I use very similar code to display data but I have a custom adapter. If you are just using text and data it would work fine. If you want something more robust you can use lazy loader/image manager for images.
Since an http request is time consuming, using an async task will be the best idea. Otherwise the main thread may throw errors. The class shown below can do the download asynchronously
private class jsonLoad extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
// Instantiate a JSON object from the request response
try {
JSONObject jsonObject = new JSONObject(result);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File file = new File(getApplicationContext().getFilesDir(),"nowList.cache");
try {
file.createNewFile();
FileOutputStream writer = openFileOutput(file.getName(), Context.MODE_PRIVATE);
writer.write(result);
writer.flush();
writer.close();
}
catch (IOException e) { e.printStackTrace(); return false; }
}
}
Unlike the other answer, here the downloaded json string itself is saved in file. So Serialization is not necessary
Now loading the json from url can be done by calling
jsonLoad jtask=new jsonLoad ();
jtask.doInBackground("http:www.json.com/urJsonFile.json");
this will save the contents to the file.
To open the saved json string
File file = new File(getApplicationContext().getFilesDir(),"nowList.cache");
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//print log
}
JSONObject jsonObject = new JSONObject(text);