Get last JSON array element with HTTP request - java

Is it possible to take the last / penultimate element of a JSON Array file hosted on GitHub, without downloading the entire file?
Because the file is 10 MB, I only need the last two cells of the array, in fact every time I go to get the information it takes a lot of time to load due to the weight of the file.
File link: https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-json/dpc-covid19-ita-regioni.json
I retrive the information with this code:
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, JSON_OLD, null, response -> {
try{
for(int i = response.length() - 42; i < response.length() - 21; i++){
JSONObject jsonObject = response.getJSONObject(i);
oldRegionData.add(new RegionData(Integer.parseInt(jsonObject.getString("dimessi_guariti")),Integer.parseInt(jsonObject.getString("deceduti")), jsonObject.getString("denominazione_regione"), Integer.parseInt(jsonObject.getString("nuovi_positivi"))));
}
getNewData(queue);
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> Log.println(Log.ERROR,"Error", "Error while performing this action"));
queue.add(jsonArrayRequest);

As far as I know, there is no way to "jump" to the end of the call response.
Still, I would approach this, this way:
If the data changes constantly:
Recieve the data at a fixed interval and not every time I need it.
Get the data and save it somewhere (through an Object or cache the part of the file that you need in a temporary place).
If the data does not change
Fetch the data when the application starts running and use an Object to keep the data needed

Related

Downloading attachments from unseen messages

I work on university project in java. I have to download attachments from new emails using GMAIL API.
I successfully connected to gmail account using OAuth 2.0 authorization.
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_READONLY);
I tried to get unseen mails using
ListMessagesResponse listMessageResponse = service.users().messages().list(user).setQ("is:unseen").execute();
listMessageResponse is not null but when I call method .getResultSizeEstimate() it returns 0
also I tried to convert listMessageResponse to List < Message > (I guess this is more usable) using
List<Message> list = listMessageResponse.getMessages();
But list launches NullPointerException
Then tried to get each attachment with
for(Message m : list) {
List<MessagePart> part = m.getPayload().getParts();
for(MessagePart p: part) {
if(p.getFilename()!=null && p.getFilename().length()>0) {
System.out.println(p.getFilename()); // Just to check attachment filename
}
}
}
Is my approach correct (if not how to fix it) and how should I download those attachments.
EDIT 1:
Fixed q parameter, I mistakenly wrote is:unseen instead of is:unread.
Now app reaches unread mails successfully.
(For example there was two unread mails and both successfully reached, I can get theirs IDs easy).
Now this part trows NullPointerException
List<MessagePart> part = m.getPayload().getParts();
Both messages have attachments and m is not null (I get ID with .getID())
Any ideas how to overcome this and download attachment?
EDIT 2:
Attachments Downloading part
for(MessagePart p : parts) {
if ((p.getFilename() != null && p.getFilename().length() > 0)) {
String filename = p.getFilename();
String attId = p.getBody().getAttachmentId();
MessagePartBody attachPart;
FileOutputStream fileOutFile = null;
try {
attachPart = service.users().messages().attachments().get("me", p.getPartId(), attId).execute();
byte[] fileByteArray = Base64.decodeBase64(attachPart.getData());
fileOutFile = new FileOutputStream(filename); // Or any other dir
fileOutFile.write(fileByteArray);
fileOutFile.close();
}catch (IOException e) {
System.out.println("IO Exception processing attachment: " + filename);
} finally {
if (fileOutFile != null) {
try {
fileOutFile.close();
} catch (IOException e) {
// probably doesn't matter
}
}
}
}
}
Downloading working like charm, tested app with different type of emails.
Only thing left is to change label of unread message (that was reached by app) to read. Any tips how to do it?
And one tiny question:
I want this app to fetch mails on every 10 minutes using TimerTask abstract class. Is there need for manual "closing" of connection with gmail or that's done automatically after run() method iteration ends?
#Override
public void run(){
// Some fancy code
service.close(); // Something like that if even exists
}
I don't think ListMessagesResponse ever becomes null. Even if there are no messages that match your query, at least resultSizeEstimate will get populated in the resulting response: see Users.messages: list > Response.
I think you are using the correct approach, just that there is no message that matches your query. Actually, I never saw is:unseen before. Did you mean is:unread instead?
Update:
When using Users.messages: list only the id and the threadId of each message is populated, so you cannot access the message payload. In order to get the full message resource, you have to use Users.messages: get instead, as you can see in the referenced link:
Note that each message resource contains only an id and a threadId. Additional message details can be fetched using the messages.get method.
So in this case, after getting the list of messages, you have to iterate through the list, and do the following for each message in the list:
Get the message id via m.getId().
Once you have retrieved the message id, use it to call Gmail.Users.Messages.Get and get the full message resource. The retrieved message should have all fields populated, including payload, and you should be able to access the corresponding attachments.
Code sample:
List<Message> list = listMessageResponse.getMessages();
for(Message m : list) {
Message message = service.users().messages().get(user, m.getId()).execute();
List<MessagePart> part = message.getPayload().getParts();
// Rest of code
}
Reference:
Class ListMessagesResponse
Users.messages: list > Response

How to assert two JSON objects which have the same keys but different in values inside of a JSON array

I have to assert two json objects which have the same key and they are included in a JSON array as below.
Response value
[{"message":"Rest Endpoint should not be empty"},{"message":"Invalid URL"}]
But I am facing an issue when I am asserting the response, the objects do not receive as the way I am trying to assert as the order of the response objects are changing sometimes which leads to an assertion failure.
Below is the code which I am currently using to assert the objects.
Assert.assertEquals(jsonArray.getJSONObject(0).get("message").toString(), "Rest Endpoint should not be empty");
Assert.assertEquals(jsonArray.getJSONObject(1).get("message").toString(), "Invalid URL");
Sometimes what I received leads to an assertion error.
jsonArray.getJSONObject(0).get("message").toString() as "Invalid URL" and
jsonArray.getJSONObject(1).get("message").toString() as "Rest Endpoint should not be empty"
Full code Block
//Requesting the resource API (save) with Payload
Response response = RestAssured.given().contentType("application/json").body(mydata).post("/api/v1/applications");
logger.info("/Save - Request sent to the API");
//Check valid Json responce
JSONArray jsonArray = new JSONArray(response.body().asString());
System.out.println(jsonArray.length());
Assert.assertEquals(jsonArray.length(), 2);
logger.info("/Save - Json Response validity pass");
//Check Response status code
Assert.assertEquals(response.getStatusCode(), 400);
logger.info("/Save - Responce code 400 OK");
//Check Response Objects received
Assert.assertEquals(jsonArray.getJSONObject(0).get("message").toString(), "Rest Endpoint should not be empty");
Assert.assertEquals(jsonArray.getJSONObject(1).get("message").toString(), "Invalid URL");
logger.info("/getAllApplications - Json Response received as :" + jsonArray.getJSONObject(0).get("message").toString());
logger.info("/getAllApplications - Json Response received as :" + jsonArray.getJSONObject(1).get("message").toString());
logger.info("/Save -3 API Testing Completed [Test 'RestEndPoint' field validation]");
Found the Solution
//Create a string list and iterate the Json array to fetch the required text with the same key
List<String> responseList = new ArrayList<String>(jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
responseList.add((jsonArray.getJSONObject(i).getString("message")));
}
//Assert the list
org.junit.Assert.assertThat(responseList, hasItems("Rest Endpoint should not be empty", "Invalid URL"));
You can use hasItem and assertThat, just convert jsonArray to List.
Assert.assertThat(Arrays.asList(exampleStringArray), hasItem("Rest Endpoint should not be empty"));
Assert.assertThat(Arrays.asList(exampleStringArray), hasItem("Invalid URL"));
where hasItem is part of org.hamcrest.core.
If you are using Maven for your use case, I would include this library
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
This should help you in the getting the objects compared without having to worry about the order.
Here is a link in how to use it as well.

Cannot put DesignDocuments back

I am trying to delete all documents from a database but i want to preserve the views. So i tried
//First, get all DesignDocument for the current database
List<DesignDocument> dbDesigns = cloudant.getDesignDocumentManager().list();
//Now, we delete the database
cloudantClient.deleteDB(_DatabaseName);
//now we create the database again
cloudant = cloudantClient.database(_DatabaseName, true);
//finally, try to add the DesignDocuments back
if (dbDesigns != null && dbDesigns.size() > 0) {
for (DesignDocument dDoc : dbDesigns) {
Response response = cloudant.getDesignDocumentManager().put(dDoc);
System.out.println(response);
}
}
but i get error at
Response response = cloudant.getDesignDocumentManager().put(dDoc);
java.lang.IllegalArgumentException: rev should be null
at com.cloudant.client.org.lightcouch.internal.CouchDbUtil.assertNull(CouchDbUtil.java:72)
at com.cloudant.client.org.lightcouch.CouchDbClient.put(CouchDbClient.java:410)
at com.cloudant.client.org.lightcouch.CouchDbClient.put(CouchDbClient.java:394)
at com.cloudant.client.org.lightcouch.CouchDatabaseBase.save(CouchDatabaseBase.java:196)
at com.cloudant.client.api.Database.save(Database.java:710)
at com.cloudant.client.api.DesignDocumentManager.put(DesignDocumentManager.java:122)
is there any other way to preserve the views?
I'm suspecting the error is raised because the document revision property (_rev) is set in dDoc. However, since a document with a matching id is not found in the database the put method raises an error. Try setting the revision to null using the setRevision method prior to invoking put
dDoc.setRevision(null);
Response response = cloudant.getDesignDocumentManager().put(dDoc);

Android Firebase - Can't receive proper JSON from Firebase snapshot

My android app connects to Firebase and pulls "Alert Objects" that are sent there by my server.
When I export the data from Firebase, I get a beautifully formated JSON representation of the data.
Problem:
When I pull the data to my android device using a DataSnapshot, the data has '=' (equals signs) instead of ':' (semicolons). Also the quotations are not there.
When I try to do something like JSONObject alert = new JSONObject(data.getValue().toString()); I get errors for obvious reasons. I say obvious because if you look at what my code prints to the console you can see that it is no longer in valid JSON format.
A friend mentioned that I need to do something with encoding but we didn't have time to discuss it.
How can I iterate through these (kinda weird) Alert Objects that I have created and turn them into JSON objects within my Java so that I can access their properties like alert.date and alert.message.
I thought screenshots would help you see what I am doing. The firebase is not secured at all so you can feel free to take a look at it. It won't really do much and when I go to production I will be moving it anyways.
I am sure this is a super easy question to answer, I am just not too well versed with JSON and encoding as a whole.
Thanks!
you can it using gson library
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
/*JSONObject jsonObject = null;
try {
jsonObject=new JSONObject();
} catch (JSONException e) {
e.printStackTrace();
}*/
Gson gson = new Gson();
String s1 = gson.toJson(dataSnapshot.getValue());
JSONArray object = null;
try {
object = new JSONArray(s1);
} catch (JSONException e) {
e.printStackTrace();
}
JSONArray jsonArray = object;
Log.e("string", s1);
}
You cannot access JSON natively in Java.
But the Firebase DataSnapshot class provides everything you need.
If you have a DataSnapshot of the data at the fbAlerts in your screenshot, you can print the date+message and recipients for each:
for (DataSnapshot alert: alerts.getChildren()) {
System.out.println(alert.child("date").getValue();
System.out.println(alert.child("message").getValue();
for (DataSnapshot recipient: alert.child("recipients").getChildren()) {
System.out.println(recipient.child("name").getValue();
}
}
Alternatively, you can build a Java class that represents an alert. See the Firebase guide on reading data in Android for examples of that.
Use this way to convert the jsonObject form the dataSnapshot
Map<String, String> value = (Map<String, String>) dataSnapshot.getValue();
Log.i("dataSnapshot", "dataSnapshot" + new JSONObject(value));
From the above code extract, it looks like you have a JSONArray rather than a JSONObject.
In which case, you need to do something like the following:
// Find the right array object
JSONArray jsonArray = response.getJSONArray("fbAlerts");
// Loop through the array
for (int i=0; i< jsonArray.length(); i++) {
JSONObject myObj = jsonArray.getJSONObject(i);
strMsg = myObj.getString("message");
}
In the example - when you have repeating groups, this would seem to indicate an array and therefore needs an iterator to access the object contents.

How to create a Restful web-service of JSON data in java,tomcat,eclipse

I have a JSON data like this. I want to create a Restful web-service that generates a JSON output like the link above.
I looked at How to Create a Restful service for a Huge JSON data using Java eclipse Tomcat7.0
I want to add this in the above condition:
{
status: "ok",
count: 10,
pages: 6,
category:{
previous answer is this,..
{
category:{/[
I want this
{
status: "ok",
count: 10,
pages: 6,
category:{
Take a look at this answer
A typical JSON is as shown below
{
"name":"Ersin",
"surname":"Çetinkaya",
"age":"25",
"address":[{"city": "Bursa","country": "Türkiye","zipCode": "33444"}],
"phones": ["234234242","345345354"]
}
Java code for creating the above JSON is given below
public JSONObject getValues()
{
JSONObject jsonobj=new JSONObject();
jsonobj.put("name","Ersin");
jsonobj.put("surname","Çetinkaya");
jsonobj.put("age","25");
JSONArray obj = new JSONArray();
HashMap rows=new HashMap();
rows.put("city","Bursa");
rows.put("country","Türkiye");
rows.put("zipCode","33444");
obj.put(rows);
jsonobj.put("address", obj);
JSONArray phobj = new JSONArray();
phobj.put("234234242");
phobj.put("345345354");
jsonobj.put("phones", phobj);
System.out.println(jsonobj.toString());
return jsonobj.toString();
}
Those first few lines can be added as additional keys to the parent jsonobj:
jsonobj.put("status", "ok");
jsonobj.put("count", 10);
jsonobj.put("pages", totalPages);
jsonobj.put("category", categoryMap);
How you generate these variables will depend on where you are getting your data from. Is it a database for example?
The count and pages would seem to indicate that there are between 51 - 60 items available, with 10 items per page and 6 pages.
The Status variable could be used to indicate an error, so another possible value could be:
jsonobj.put("status", "error");
jsonobj.put("errorcode", "101");
jsonobj.put("error message", "big database error");
This allows the client to check the status string in the response and catch errors gracefully.

Categories