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
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)
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);
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);
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.
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);