Issue extracting JSON response data - java

I'm trying to build an app for a course that extracts news data from a particular JSON and displays in on the screen. I logged my errors, and it's rejecting the way I'm extracting my data. Here's a sample of the json layout:
"response": {
"status": "ok",
"userTier": "developer",
"total": 2050598,
"startIndex": 1,
"pageSize": 10,
"currentPage": 1,
"pages": 205060,
"orderBy": "newest",
"results": [
{
"id": "technology\/2018\/jul\/26\/facebook-stock-price-falling-what-does-it-mean-analysis",
"type": "article",
"sectionId": "technology",
"sectionName": "Technology",
"webPublicationDate": "2018-07-26T19:12:07Z",
"webTitle": "Does Facebook's plummeting stock spell disaster for the social network?",
"webUrl": "https:\/\/www.theguardian.com\/technology\/2018\/jul\/26\/facebook-stock-price-falling-what-does-it-mean-analysis",
"apiUrl": "https:\/\/content.guardianapis.com\/technology\/2018\/jul\/26\/facebook-stock-price-falling-what-does-it-mean-analysis",
"isHosted": false,
"pillarId": "pillar\/news",
"pillarName": "News"
},
and here's my resulting code that it's not liking:
// Returns News List from JSON Response
private static List<News> extractFeatureFromJson(String newsJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(newsJSON)) {
return null;
}
// Create an empty ArrayList that we can add news stories to
List<News> news = new ArrayList<>();
// Try to parse the JSON response string. Errors will be sent to log.
try {
// Create a JSONObject from the JSON response string
JSONObject baseJsonResponse = new JSONObject(newsJSON);
// Extract the JSONArray associated with the key called "response",
JSONArray newsArray = baseJsonResponse.getJSONArray("response");
// For each article in the newsArray, create an {#link News} object
for (int i = 0; i < newsArray.length(); i++) {
// Get a single article at position i within the list of articles
JSONObject currentNews = newsArray.getJSONObject(i);
// Extract results for news story
JSONObject results = currentNews.getJSONObject("results");
// Extract the value for the key called webTitle
String webTitle = results.getString("webTitle");
// Extract the value for the key called "sectionName"
String sectionName = results.getString("sectionName");
// Extract the value for the key called "webPublicationDate"
long webPublicationDate = results.getLong("webPublicationDate");
// Extract the value for the key called "webUrl"
String webUrl = results.getString("webUrl");
// Create a new {#link Earthquake} object with the title, category, date,
// and url from the JSON response.
News news1 = new News(webTitle, sectionName, webPublicationDate, webUrl);
// Add the new {#link News} to the list of articles.
news.add(news1);
}
} catch (JSONException e) {
// If an error is thrown when executing any of the above statements in the "try" block,
// catch the exception here, so the app doesn't crash. Print a log message
// with the message from the exception.
Log.e("QueryUtils", "Problem parsing the Guardian JSON results", e);
}
// Return the list of articles
return news;
}
I don't understand what the heck I'm doing wrong, because I feel like I'm replicating the data, right? Anyway, I have no idea.
It's also throwing me errors for my Loader:
public class NewsLoader extends AsyncTaskLoader<List<News>> {
// Tag for Log Messages
private static final String LOG_TAG = NewsLoader.class.getName();
// Query URL
private String mUrl;
/**
* Constructs a new {#link NewsLoader}.
* #param context of the activity
* #param url to load data from
*/
public NewsLoader(Context context, String url) {
super(context);
mUrl = url;
}
#Override
protected void onStartLoading() {
forceLoad();
}
#Override
//Background Thread
public List<News> loadInBackground() {
if (mUrl == null) {
return null;
}
// Perform the network request, parse the response, and extract news articles.
List<News> news = QueryUtils.fetchNewsData(mUrl);
return news;
} }
Errors thrown:
at com.example.android.newsapp.QueryUtils.extractFeatureFromJson(QueryUtils.java:135)
at com.example.android.newsapp.QueryUtils.fetchNewsData(QueryUtils.java:44)
at com.example.android.newsapp.NewsLoader.loadInBackground(NewsLoader.java:42)
at com.example.android.newsapp.NewsLoader.loadInBackground(NewsLoader.java:11)

1) The "response" is a JSON Object, not JSON Array.
2) The "results" is a JSON Array, not a JSON Object.
3) The webPublicationDate type is Sting not long.
In order to parse the Json correctly try this:
// Returns News List from JSON Response
private static List<News> extractFeatureFromJson(String newsJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(newsJSON)) {
return null;
}
// Create an empty ArrayList that we can add news stories to
List<News> news = new ArrayList<>();
// Try to parse the JSON response string. Errors will be sent to log.
try {
// Create a JSONObject from the JSON response string
JSONObject baseJsonResponse = new JSONObject(newsJSON);
// Extract the JSONArray associated with the key called "response",
JSONObject resultObject = baseJsonResponse.getJSONObject("response");
// Extract JSON array of resultObject
JSONArray newsArray = resultObject.getJSONArray("results");
// For each article in the resultObject, create an {#link News} object
for (int i = 0; i < newsArray.length(); i++) {
// Get a single article at position i within the list of articles
JSONObject currentNews = newsArray.getJSONObject(i);
// Extract the value for the key called webTitle
String webTitle = currentNews.getString("webTitle");
// Extract the value for the key called "sectionName"
String sectionName = currentNews.getString("sectionName");
// Extract the value for the key called "webPublicationDate"
String webPublicationDate = currentNews.getString("webPublicationDate");
// Extract the value for the key called "webUrl"
String webUrl = currentNews.getString("webUrl");
// Create a new {#link Earthquake} object with the title, category, date,
// and url from the JSON response.
// CHANGE YOUR NEWS CLASS' webPublicationDate FIELD TO STRING OR
// DON'T FORGET TO CONVERT IT TO LONG!!!!
News news1 = new News(webTitle, sectionName, webPublicationDate, webUrl);
// Add the new {#link News} to the list of articles.
news.add(news1);
}
} catch (JSONException e) {
// If an error is thrown when executing any of the above statements in the "try" block,
// catch the exception here, so the app doesn't crash. Print a log message
// with the message from the exception.
Log.e("QueryUtils", "Problem parsing the Guardian JSON results", e);
}
// Return the list of articles
return news;
}
Hope I could help you!
Best regards,
Csongor

Related

Next Page Token is not functional and display only maximum (50) results

I am trying to fetch all videos of a channel using youtube data api, but my code is giving error and doesn't respond to PAGE token
displayVideos();
}
private void displayVideos ()
{
RequestQueue requestQueue= Volley.newRequestQueue(this);
StringRequest stringRequest=new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
System.out.println(jsonObject.get("nextPageToken"));
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
if (jsonObject1.has("id")){
JSONObject jsonVideoId=jsonObject1.getJSONObject("id");
if (jsonVideoId.has("kind")){
if(jsonVideoId.getString("kind").equals("youtube#video")){
JSONObject jsonObjectSnippet = jsonObject1.getJSONObject("snippet");
JSONObject jsonObjectDefault=jsonObjectSnippet.getJSONObject("thumbnails").getJSONObject("medium");
String video_id=jsonVideoId.getString("videoId");
VideoDetails vd=new VideoDetails();
vd.setVideoId(video_id);
vd.setTitle(jsonObjectSnippet.getString("title"));
vd.setDescription(jsonObjectSnippet.getString("description"));
vd.setUrl(jsonObjectDefault.getString("url"));
videoDetailsoArrayList.add(vd);
}
// recyclerView.setAdapter(adapter);
// adapter.notifyDataSetChanged();
}
}
}
}catch (JSONException e) {
e.printStackTrace();
}
the url I am trying to parse is
String url="https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCVMWWQ985A_-SESZUy_SsVQ&maxResults=50&pageToken="+nextPageToken+"&order=date&pageToken=CAUQAA&key=API_KEY";
I have been searchingb to apply nextpage token or page token in android studio but couldnt get specific tutorial. there are many examples but being naive in android studio I cant implement it into my code.
Please note that your URL does contain two instances of the parameter pageToken:
"https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCVMWWQ985A_-SESZUy_SsVQ&maxResults=50&pageToken="+nextPageToken+"&order=date&pageToken=CAUQAA&key=API_KEY".
It should have only one for that to work OK; to be more precise, your URL should contain only this instance: pageToken="+nextPageToken+".
On the other hand, your code above does not show the loop implementing pagination. That is that you haven't shown the piece of code where you actually assign a valid value to the variable nextPageToken.
Therefore I cannot tell if your program will work or not.
The pagination loop would look like this:
// initially no pageToken
nextPageToken = null;
// URL as above, without the parameter pageToken
url = ...
do {
invoke the API on the URL: url + (nextPageToken != null ? "&pageToken=" + nextPageToken : "")
nextPageToken = jsonObject.get("nextPageToken");
} while (nextPageToken != null)

How to add json to arraylist? [duplicate]

This question already has answers here:
How do I parse JSON in Android? [duplicate]
(3 answers)
Closed 4 years ago.
Hello everyone I'm kind of new in this field.
I made a rest request for project and I got this response:
{"success":true,"timestamp":1524649444,"base":"EUR","date":"2018-04-25","rates":{"AED":4.486623,"AFN":85.583411,"ALL":128.283655,"AMD":585.986726,"ANG":2.175126,"AOA":270.568194,"ARS":24.745299,"AUD":1.609775,"AWG":2.1 // and so on.
how can I insert the currency and his value to arraylist?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fixer_request);
System.out.println("-->rest");
String url = "http://data.fixer.io/api/latest?access_key=7e4976fbeb5d633e337487fea31fd7ca";
RequestQueue requestQueue= Volley.newRequestQueue(this);
JsonObjectRequest objectRequest= new JsonObjectRequest(
Request.Method.GET,
url,
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("rest Response",response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("rest Response",error.toString());
}
}
);
requestQueue.add(objectRequest);
}
You have to change your JSON response like this:
{"success":true,"timestamp":1524649444,"base":"EUR","date":"2018-04-25","rates":[{"currency_name":"AED","currency_value":"4.486623"},{"currency_name":"AFN","currency_value":"85.583411"},{"currency_name":"ALL","currency_value":"128.283655"},{"currency_name":"AMD","currency_value":"585.986726"}]}
In your JSON there is no array to from which you can add value in array list.
If you can't change your JSON response than you have to pre-declare all type of currency in your array list and than add there currency accordingly.
Use Gson library to convert json object to Java object easily
google-gson
Create a JSONObject:
JSONObject jObject = new JSONObject(result);
To get a specific string
String aJsonString = jObject.getString("STRINGNAME");
To get a specific boolean
boolean aJsonBoolean = jObject.getBoolean("BOOLEANNAME");
To get a specific integer
int aJsonInteger = jObject.getInt("INTEGERNAME");
To get a specific long
long aJsonLong = jObject.getBoolean("LONGNAME");
To get a specific double
double aJsonDouble = jObject.getDouble("DOUBLENAME");
To get a specific JSONArray:
JSONArray jArray = jObject.getJSONArray("ARRAYNAME");
To get the items from the array
for (int i=0; i < jArray.length(); i++)
{
try {
JSONObject oneObject = jArray.getJSONObject(i);
// Pulling items from the array
String oneObjectsItem = oneObject.getString("STRINGNAMEinTHEarray");
String oneObjectsItem2 = oneObject.getString("anotherSTRINGNAMEINtheARRAY");
} catch (JSONException e) {
// Oops
}
}
you can from http://www.jsonschema2pojo.org/ to convert json to java class annotation base are clear code
and you can use from library retrofit Gson base are easy
or use :
JSONArray jArray2 = jArray.getJSONArray("PreFactorHotels");
for (int i = 0; i < jArray2.length(); i++) {
hotelPreFactorModels.add(new HotelPreFactorModel(jArray2.getJSONObject(i).getString("HotelNameE"),
Utility.dateShow(jArray2.getJSONObject(i).getString("HotelChekin"))
, Utility.dateShow(jArray2.getJSONObject(i).getString("HotelChekout")),
jArray2.getJSONObject(i).getString("AdlCount"),
jArray2.getJSONObject(i).getString("ChdCount"),jArray2.getJSONObject(i).getString("RoomTitleFa")));
}
USING GSON libray
it requires three steps
String afikJson = "YOUR JSON...";
Gson gson = new Gson();//create Gson object
//and create Type object with arrayList as a type of data
Type afikListType = new TypeToken<ArrayList<Afik>>(){}.getType();
//map your JSON
List<Afik> afikList = gson.fromJson(afikJson, afikListType);

Adding a new element to an array in the json object java

I am writing automation script to validate json responses of REST APIs and i am using faster xml to serialize and convert java object to json format.
I have a user case where I have to get the json response and add a new array element to an existing array and post it back.
The json response after GET looks like this :
{
"name":"test",
"id":"1234",
"nodes":[
{
"nodeId":"node1"
},
{
"nodeId":"node2"
}
]
}
To this json response, I need to add a third entry for nodes array
{ "nodeId": "node3" } and then post this.
Can someone please help me understand how to add a new array element to an existing array?
You can try:
//Your JSON response will be in this format
String response = "{ \"name\":\"test\", \"id\":\"1234\", \"nodes\":[ { \"nodeId\":\"node1\" }, { \"nodeId\":\"node2\" } ] }";
try {
JSONObject jsonResponse = new JSONObject(response);
JSONArray nodesArray = jsonResponse.getJSONArray("nodes");
JSONObject newEntry = new JSONObject();
newEntry.put("nodeId","node3");
nodesArray.put(newEntry);
jsonResponse.put("nodes",nodesArray);
} catch (JSONException e) {
e.printStackTrace();
}
Now you can post your jsonResponse.toString() as required.
I would rather go for cleaner approach, create Object with below structure -
public class Response{
private String name;
private int id;
private List<Node> nodes;
<Getter & Setter>
}
public class Node{
private String nodeId;
}
Serialize the json -
Response response = objectMapper.readValue(responseJson,
Response.class);
Add the new incoming node object to response -
response.getNodes().add(New Node("{new node Value}"));
Deserialize before post -
objectMapper.writeValueAsString(response);

org.json.JSONException: End of input at character 0 of

There is some issue with the JSONObjectRequest in Volley library to receive the JSON data. I suppose I am going wrong somewhere in receiving the JSON object in the Java code. Following is my JSON output coming as a response from the php file hosted on server:
{"workers":[
{"id":"1","name":"Raja","phonenumber":"66589952","occupation":"Plumber","location":"Salunke Vihar","rating":"4","Review":"Hard Worker","price":"80"},
{"id":"2","name":"Aman","phonenumber":"789456","occupation":"Plumber","location":"Wakad","rating":"4","Review":"Good","price":"80"}
],
"success":1}
Following is clode from the Java file where I am using the JSON request using Volley library:
JsonObjectRequest jsonRequest = new JsonObjectRequest (Request.Method.POST, url,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
// I should receive the success value 1 here
int success = response.getInt("success");
//and should receive the workers array here
Log.d("response",response.getJSONArray("workers").toString());
Log.d("success",""+success);
} catch (JSONException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_LONG).show();
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
//Finally initializing our adapter
adapter = new WorkerAdapter(listWorkers);
recyclerView.setAdapter(adapter);
//adapter is working fine
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("error",error.toString());
Toast.makeText(getApplicationContext(),error.toString(),Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
params.put("tag", "get_list");
params.put("service", service);
return params;
}
Running the above code it goes to the error listener and gives the output as org.json.JSONException: End of input at character 0 of.
But if I use StringRequest in place of JsonObjectRequest and receive the JSON response as a string then I am able to receive the output as a String but I can't use it further. So, please let me know where I am going wrong in receiving the JSONdata and suggest me the changes in the code that I must do.
EDIT- I am adding the php file which is returning the JSON object. Please let me know if there is some error over here:
<?php
error_reporting(0);
include("config.php");
if($_SERVER['REQUEST_METHOD']=='POST'){
$tag = $_POST['tag'];
// array for JSON response
$response = array();
if ($tag == 'get_list') {
// Request type is check Login
$service = $_POST['service'];
//echo json_encode($service);
// get all items from myorder table
$result = mysql_query("SELECT * FROM Workers WHERE Occupation = '$service'") or die(mysql_error());
if (mysql_num_rows($result) > 0) {
$response["workers"] = array();
while ($row = mysql_fetch_array($result)) {
// temp user array
$item = array();
$item["id"] = $row["wID"];
$item["pic"] = $row["Pic"];
$item["name"] = $row["Name"];
$item["phonenumber"] = $row["Phone Number"];
$item["occupation"] = $row["Occupation"];
$item["location"] = $row["Location"];
$item["rating"] = $row["Rating"];
$item["Review"] = $row["Review"];
$item["price"] = $row["Price"];
// push ordered items into response array
array_push($response["workers"], $item);
}
// success
$response["success"] = 1;
}
else {
// order is empty
$response["success"] = 0;
$response["message"] = "No Items Found";
}
}
echo json_encode($response);
}
?>
When I ran the api end point I have got the following result instead of the one that you have been telling so. So stop giving irrelevant data.
"Plumber"{"workers":[{"id":"1","pic":"ttp:\/\/vorkal.com\/images\/vorkal_cover.PNG","name":"Raja","phonenumber":"66589952","occupation":"Plumber","location":"Salunke Vihar","rating":"4","Review":"Hard Worker. Very Professional.","price":"80"},{"id":"2","pic":"http:\/\/vorkal.com\/images\/vorkal_cover.PNG","name":"Aman","phonenumber":"789456","occupation":"Plumber","location":"Wakad","rating":"4","Review":"Good","price":"80"}],"success":1}
Where Plumber is not the tag at all, hence throws error as the same is not valid json string. There's error in your server side scripting. I request you to send the complete script without modification.
If you are not getting the JSONObject that means the following is a malformed json. Thus you can try the following code in server side
function utf8ize($d) {
if (is_array($d)) {
foreach ($d as $k => $v) {
$d[$k] = $this->utf8ize($v);
}
} else if (is_string ($d)) {
return utf8_encode($d);
}
return $d;
}
where$d is the string/response. use it as echo json_encode($this->utf8ize($detail));
Also try the following in client side code
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(result1));
reader.setLenient(true);
You may refer the solution to this question here click here
you can use Gson to convert json string to object
Gson gson = new Gson();
GetWorkersResponse getWorkersResponse =gson.fromJson(response,GetWorkersResponse.class);
class GetWorkersResponse {
public boolean success;
public List<Worker> workers = new ArryList<>();
}
It's work for me.
Can you check that server is returning you a JSONObject and not the string? In Volley if the type of response is different then it will return the error.

Arraylist is coming as string in while sending in webservice

JSONObject myObject = new JSONObject();
try {
testVoList.add(new TestVO(1L, "HAI1"));
testVoList.add(new TestVO(2L, "HAI2"));
myObject.put("name", testVoList);
} catch (JSONException ex) {
}
String s = URLEncoder.encode(myObject.toString(), "UTF-8");
URL url = new URL("urlName/"+s);
CODE IN WEBSERVICE TO RECIEVE DATA:
#POST
#Path("/urlName/{test}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String saveSurveyresponseData(#PathParam("test") JSONObject responseData)
{
JSONArray.fromObject(responseData.getString("name")).get(0);
return "HAI";
}
Here i am getting test.TestVO#c2ea3f(Hashcode) for
JSONArray.fromObject(responseData.getString("name")).get(0);
How can I access my list of objects values in my webservice.
Can you suggest me a solution?
I believe the following statement:
JSONArray.fromObject(responseData.getString("name")).get(0);
is returning the list. So simply assign it to a list reference as mentioned here:
List<TestVO> listOfTestVO = JSONArray.fromObject(responseData.getString("name")).get(0);
Now simply get the elements as:
listOfTestVO.get(1);

Categories

Resources