HttpRequest in java with GSON and multiple elements - java

I'm trying to get the "symbol" of a JSON HttpRequest in Java. I want to use GSON of google but, I can't reach any value ... I'm always with a null value in my object... I know that the error are "stock.symbol" I certainly need to put some "node" before ... I'm lost ... so ...
here the code :
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://yahoo-finance-low-latency.p.rapidapi.com/v6/finance/quote?symbols=AAPL&lang=en&region=CA"))
.header("x-rapidapi-key", "---")
.header("x-rapidapi-host", "***")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
try {
HttpResponse<String> reponse = null;
reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.print(reponse.body());
Gson gson = new Gson();
Stock stock = gson.fromJson(reponse.body(), Stock.class);
System.out.println("******************************************************");
System.out.println(stock.symbol + stock.displayName + stock.quoteType);
System.out.println("******************************************************");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
here my output, you will be eable to see the answer from the api in JSON format :
{"quoteResponse":{"result":[{"language":"en-US","region":"CA","quoteType":"EQUITY","quoteSourceName":"Nasdaq Real Time Price","triggerable":true,"currency":"USD","firstTradeDateMilliseconds":345479400000,"priceHint":2,"postMarketChangePercent":-0.0956731,"postMarketTime":1621641596,"postMarketPrice":125.31,"postMarketChange":-0.120003,"regularMarketChange":-1.8799973,"regularMarketChangePercent":-1.4767083,"regularMarketTime":1621627203,"averageAnalystRating":"2.0 - Buy","tradeable":false,"esgPopulated":false,"marketState":"POSTPOST","regularMarketPrice":125.43,"regularMarketDayHigh":128.0,"regularMarketDayRange":"125.21 - 128.0","regularMarketDayLow":125.21,"regularMarketVolume":79152773,"regularMarketPreviousClose":127.31,"bid":125.37,"ask":125.37,"bidSize":12,"askSize":10,"fullExchangeName":"NasdaqGS","financialCurrency":"USD","regularMarketOpen":127.82,"averageDailyVolume3Month":103188411,"averageDailyVolume10Day":86685085,"fiftyTwoWeekLowChange":47.1575,"fiftyTwoWeekLowChangePercent":0.60247856,"fiftyTwoWeekRange":"78.2725 - 145.09","fiftyTwoWeekHighChange":-19.659996,"fiftyTwoWeekHighChangePercent":-0.13550209,"fiftyTwoWeekLow":78.2725,"fiftyTwoWeekHigh":145.09,"dividendDate":1620864000,"earningsTimestamp":1619627400,"earningsTimestampStart":1627469940,"earningsTimestampEnd":1627905600,"trailingAnnualDividendRate":0.82,"trailingPE":28.192854,"trailingAnnualDividendYield":0.006440971,"epsTrailingTwelveMonths":4.449,"epsForward":5.36,"epsCurrentYear":5.2,"priceEpsCurrentYear":24.121155,"sharesOutstanding":16687599616,"bookValue":4.146,"fiftyDayAverage":130.1347,"fiftyDayAverageChange":-4.7047043,"fiftyDayAverageChangePercent":-0.03615257,"twoHundredDayAverage":127.04788,"twoHundredDayAverageChange":-1.6178818,"twoHundredDayAverageChangePercent":-0.012734425,"marketCap":2093125599232,"forwardPE":23.40112,"priceToBook":30.253258,"sourceInterval":15,"exchangeDataDelayedBy":0,"exchange":"NMS","shortName":"Apple Inc.","longName":"Apple Inc.","messageBoardId":"finmb_24937","exchangeTimezoneName":"America/New_York","exchangeTimezoneShortName":"EDT","gmtOffSetMilliseconds":-14400000,"market":"us_market","displayName":"Apple","symbol":"AAPL"}],"error":null}}******************************************************
nullnullnull`
Process finished with exit code 0
public class Stock {
public String symbol, displayName, quoteType;}

We need to get to the JSON inside the result array:
Gson gson = new Gson();
JsonObject json = gson.fromJson(jsonStr, JsonObject.class)
.get("quoteResponse")
.getAsJsonObject()
.get("result")
.getAsJsonArray()
.get(0) // only one object in the array
.getAsJsonObject();
String symbol = json.get("symbol").getAsString();
String displayName = json.get("displayName").getAsString();
String quoteType = json.get("quoteType").getAsString();
Stock stock = new Stock(symbol, displayName, quoteType);

Related

How can I remove an attribute from Json array

My code is below in brief :
private void havayı_gösterActionPerformed(java.awt.event.ActionEvent evt) {
String WEATHER_URL = "https://api.collectapi.com/weather/getWeather?data.lang=tr&data.city="+şehir_ismi.getText();
//REQUEST GÖNDERME
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = (HttpRequest) HttpRequest.newBuilder()
.GET()
.header("content-type", "application/json")
.header("authorization", "apikey myapikey")
.uri(URI.create(WEATHER_URL))
.build();
//REQUESTE CEVAP
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String content = response.body();
JSONParser parser = new JSONParser();
Object obj;
obj = parser.parse(content);
JSONArray array = new JSONArray();
array.add(obj);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String req_result = gson.toJson(array.get(0));
String text;
text = req_result.replaceAll("\"", "")
.replaceAll("\\{", "")
.replaceAll("result:", "")
.replaceAll("\\},", "")
.replaceAll("\\,", "")
.replaceAll("\\]","")
.replaceAll("\\[","")
.replaceAll("success: true","")
.replaceAll("\\}","");
havayı_listele.setText(text);
I want to show a pretty printed data in the java swing, but attribute "icon" causes unreadability. Also Java does not support svg files. What's the easiest way to get rid of this problem ? Here is my screenshot :

OkHttp: A simple GET request: response.body().string() returns unreadable escaped unicode symbols inside json can't convert to gson

When sending a request in Postman, I get this output:
{
"valid": false,
"reason": "taken",
"msg": "Username has already been taken",
"desc": "That username has been taken. Please choose another."
}
However when doing it using okhttp, I get encoding problems and can't convert the resulting json string to a Java object using gson.
I have this code:
public static void main(String[] args) throws Exception {
TwitterChecker checker = new TwitterChecker();
TwitterJson twitterJson = checker.checkUsername("dogster");
System.out.println(twitterJson.getValid()); //NPE
System.out.println(twitterJson.getReason());
System.out.println("Done");
}
public TwitterJson checkUsername(String username) throws Exception {
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://twitter.com/users/username_available").newBuilder();
urlBuilder.addQueryParameter("username", username);
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/json; charset=utf-8")
.build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
Response response = call.execute();
System.out.println(response.body().string());
Gson gson = new Gson();
return gson.fromJson(
response.body().string(), new TypeToken<TwitterJson>() {
}.getType());
}
Which prints this:
{"valid":false,"reason":"taken","msg":"\u0414\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e","desc":"\u0414\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u043e\u0435."}
and then throws a NullPointerException when trying to access a twitterJson. Debugger shows that object as being null.
TwitterJson:
#Generated("net.hexar.json2pojo")
#SuppressWarnings("unused")
public class TwitterJson {
#Expose
private String desc;
#Expose
private String msg;
#Expose
private String reason;
#Expose
private Boolean valid;
public String getDesc() {
return desc;
}
public String getMsg() {
return msg;
}
public String getReason() {
return reason;
}
public Boolean getValid() {
return valid;
}
...
How can I fix the encoding issues with okhttp?
It is because the response object can be consumed only once. OKHTTP says that in their documentation. After the execute is invoked, you are calling the response object twice. Store the result of response.body().string() to a variable and then do the convert into GSON.
If I were to use a hello world example...
private void testOkHttpClient() {
OkHttpClient httpClient = new OkHttpClient();
try {
Request request = new Request.Builder()
.url("https://www.google.com")
.build();
Call call = httpClient.newCall(request);
Response response = call.execute();
System.out.println("First time " + response.body().string()); // I get the response
System.out.println("Second time " + response.body().string()); // This will be empty
} catch (IOException e) {
e.printStackTrace();
}
}
The reason it is empty the second time is because the response object can be consumed only once. So you either
Return the response as it is. Do not do a sysOut
System.out.println(response.body().string()); // Instead of doing a sysOut return the value.
Or
Store the value of the response to a JSON then convert it to GSON and then return the value.
EDIT: Concerning Unicode characters. It turned out since my location is not an English-speaking country, the json i was accepting was not in English as well. I added this header:
.addHeader("Accept-Language", Locale.US.getLanguage())
to the request to fix that.

ResponseBody inconsistent JSON string (OKHttp 3.10.0)

Firstly I searched about this issue but couldn't find any solution.
I am sending a POST request to a web service. This web service returns response but I see that the response is not complete.
With PostMan I get full response without issue. But OKHttp cuts the response.
public List<Product> getProducts(String token, long bill_acct_id, long customer_id, Context context) {
if(token != null && !token.equals("")) {
Gson gson = new Gson();
List<Product> prods;
Map<String, String> list_of_headers = new HashMap<>();
list_of_headers.put("WSC-AUTH-TOKEN", token);
list_of_headers.put("Accept", "application/json, text/plain, */*");
list_of_headers.put("Content-Type", "application/json");
Headers headers = Headers.of(list_of_headers);
try {
Response response = RequestSender.post2("URL", "{\"billingAccountId\":\""+bill_acct_id+"\", \"customerId\":\""+customer_id+"\"}", headers, context);
int returnCode = response.code();
ResponseBody body = response.body();
Log.e("INFO", body.string());
if (returnCode == 200) {
prods = gson.fromJson(body.string(), new TypeToken<List<Product>>() {
}.getType());
return prods;
}
} catch (Exception ex) {
Log.e("Error", ex.getMessage());
ex.printStackTrace();
}
}
return null;
}
The response:
Solved.
Response from Postman:
Solved
Anyone faced this issue? I need your help. Thanks.
**EDIT: ** Actually it was complete. Log.e() and System.out.println(); methods doesn't show complete JSON.

How to fetch user location in java web application from backend?

Problem
How to fetch user location in java web application from backend?
Solution
I tried Geolocation api to fetch latitute and latitute from the rest api but the test case failed when I deployed it on Server as it was fetching lat and long of Server Location.
And I am confused how to add other parameters to the url to make it work perfectly.
Below is my code -
public static JSONObject getLatLon() {
JSONObject Jobject = null;
String json = createJson();
LOG.info("Json is " + json);
okhttp3.RequestBody body = okhttp3.RequestBody.create(JSON, json);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://www.googleapis.com/geolocation/v1/geolocate?key=XXX")
.post(body)
.build();
try {
Response response = client.newCall(request).execute();
LOG.info("response is " + response);
String resStr = response.body().string();
LOG.info("response String is " + resStr);
Jobject = new JSONObject(resStr);
LOG.info("Json Object is " + Jobject);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return Jobject;
}
public static String createJson() {
ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
return mapper.writeValueAsString(json);
} catch (JsonProcessingException e) {
}
return null;
}
Can anyone guide me how can I fetch latitute and longitute so that endUser location can be fetched?
May I know whose coordinates you want to access? If you want to access end user / visitor IP address, the Google Geolocation API won't be working.
HTML5 geolocation is a client-side feature and required approval from client to receive their coordinates.
The best option you can try is to use the visitor IP address and estimate it using geolocation database. You can start with free IP2Location LITE DB5 with coordinates.

Java convert Json array to typed List<T>

I have a webservice that sends a typed arraylist which I capture via HttpResponse like so:
// create GET request
HttpGet httpGet = new HttpGet("http://localhost:8084/MinecraftRestServer/webresources/Items");
// execute GET request
HttpResponse response = client.execute(httpGet);
// check response
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) { // response OK
// retreive response
List<Recipe> recipesList = new ArrayList<Recipe>();
HttpEntity jsonObj = response.getEntity();
//What's next?
The array that's being sent from the webservice looks like this:
recipesList.add(new Item(1, 11, "diamond_ingot", "Diamond ingot",
"0,0,0,0,0,0,0,0,1", "air,diamond_ore"));
recipesList.add(new Item(2, 11, "iron_ingot", "Iron ingot",
"0,0,0,0,0,0,0,0,1", "air,iron_ore"));
And comes out in this format:
[{"recipeCategory":11,"recipeImageID":"diamond_ingot","recipeDescription":"Diamond ingot","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,diamond_ore","recipeID":1},{"recipeCategory":11,"recipeImageID":"iron_ingot","recipeDescription":"Iron ingot","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,iron_ore","recipeID":2},{"recipeCategory":11,"recipeImageID":"gold_ingot","recipeDescription":"Gold ingot","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,gold_ore","recipeID":3},{"recipeCategory":11,"recipeImageID":"diamond_ore","recipeDescription":"Diamond ore","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,wooden_pickaxe","recipeID":4},{"recipeCategory":11,"recipeImageID":"iron_ore","recipeDescription":"Iron ore","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,wooden_pickaxe","recipeID":5},{"recipeCategory":11,"recipeImageID":"gold_ore","recipeDescription":"Gold ore","recipeLocations":"0,0,0,0,0,0,0,0,1","usedImages":"air,wooden_pickaxe","recipeID":6},{"recipeCategory":2,"recipeImageID":"diamond_boots","recipeDescription":"Boots (Diamond)","recipeLocations":"0,0,0,1,0,1,1,0,1","usedImages":"air,diamond_ingot","recipeID":7},{"recipeCategory":2,"recipeImageID":"gold_boots","recipeDescription":"Boots (Gold)","recipeLocations":"0,0,0,1,0,1,1,0,1","usedImages":"air,gold_ingot","recipeID":8},{"recipeCategory":2,"recipeImageID":"iron_boots","recipeDescription":"Boots (Iron)","recipeLocations":"0,0,0,1,0,1,1,0,1","usedImages":"air,iron_ingot","recipeID":9},{"recipeCategory":2,"recipeImageID":"diamond_leggings","recipeDescription":"Leggings (Diamond)","recipeLocations":"1,1,1,1,0,1,1,0,1","usedImages":"air,diamond_ingot","recipeID":10},{"recipeCategory":2,"recipeImageID":"gold_leggings","recipeDescription":"Leggings (Gold)","recipeLocations":"1,1,1,1,0,1,1,0,1","usedImages":"air,gold_ingot","recipeID":11},{"recipeCategory":2,"recipeImageID":"iron_leggings","recipeDescription":"Leggings (Iron)","recipeLocations":"1,1,1,1,0,1,1,0,1","usedImages":"air,iron_ingot","recipeID":12},{"recipeCategory":2,"recipeImageID":"diamond_chestplate","recipeDescription":"Chestplate (Diamond)","recipeLocations":"1,0,1,1,1,1,1,1,1","usedImages":"air,diamond_ingot","recipeID":13},{"recipeCategory":2,"recipeImageID":"gold_chestplate","recipeDescription":"Chestplate (Gold)","recipeLocations":"1,0,1,1,1,1,1,1,1","usedImages":"air,gold_ingot","recipeID":14},{"recipeCategory":2,"recipeImageID":"iron_chestplate","recipeDescription":"Chestplate (Iron)","recipeLocations":"1,0,1,1,1,1,1,1,1","usedImages":"air,iron_ingot","recipeID":15},{"recipeCategory":2,"recipeImageID":"diamond_helmet","recipeDescription":"Helmet (Diamond)","recipeLocations":"1,1,1,1,0,1,0,0,0","usedImages":"air,diamond_ingot","recipeID":16},{"recipeCategory":2,"recipeImageID":"gold_helmet","recipeDescription":"Helmet (Gold)","recipeLocations":"1,1,1,1,0,1,0,0,0","usedImages":"air,gold_ingot","recipeID":17},{"recipeCategory":2,"recipeImageID":"iron_helmet","recipeDescription":"Helmet
My question is, how can I convert this back into an arraylist (ArrayList<Item>)
There is already an Item class present in the client application.
I've read examples about the Gson library but it seems it's not included anymore when compiling in API 17.
What would be the easiest approach?
Download and include GSON jar from here in your project if using Eclipse.
If using Android Studio then open your build.gradle and add the below to your dependencies block. Or again you can choose not to use maven and simply drop the jar in your lib folder.
compile 'com.google.code.gson:gson:2.2.4'
Next, use GSON to construct a list of items.
Make sure you have your Item.java class with same member names as in the JSON response
List<Recipe> recipesList = new ArrayList<Recipe>();
HttpEntity jsonObj = response.getEntity();
String data = EntityUtils.toString(entity);
Log.d("TAG", data);
Gson gson = new GsonBuilder().create();
recipesList = gson.fromJson(data, new TypeToken<List<Item>>() {}.getType());
Make sure you handle the exceptions appropriately.
You could use Jackson to parse the incoming JSON. (Quick introduction)
If you already have a Class with the appropriate properties, it can be as easy as something like this:
public class Items {
private List<Item> items;
// getter+setter
}
ObjectMapper mapper = new ObjectMapper();
Items = mapper.readValue(src, Items.class);
See this for more information.
Step 1 : Item obj=new Item;
Step 2: Parse the json formar for example here :
[[Example1][1]
Step 3: while parsing put ur values in obj :
obj.recipeCategory=value1;
Step 4: insret ur obj into arraylist:
arrayList.add(obj);
I think you should using json-simple library to parse string Json to JsonObject and convert to simple data type.
Example:
JSONArray arrJson = (JSONArray) parser.parse("String json");
Get each element JSONObject in JSONArray, then parse it to simple data type:
long recipeCategory = (long) jsonObject.get("recipeCategory");
You can use Gson like many users said, here is an example of a RESTfull client using Gson:
public class RestRequest {
Gson gson = new Gson();
public <T> T post(String url, Class<T> clazz,
List<NameValuePair> parameters) {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
try {
// Add your data
httppost.setEntity(new UrlEncodedFormEntity(parameters));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
StringBuilder json = inputStreamToString(response.getEntity()
.getContent());
T gsonObject = gson.fromJson(json.toString(), clazz);
return gsonObject;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// Fast Implementation
private StringBuilder inputStreamToString(InputStream is)
throws IOException {
String line = "";
StringBuilder total = new StringBuilder();
// Wrap a BufferedReader around the InputStream
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
// Read response until the end
while ((line = rd.readLine()) != null) {
total.append(line);
}
// Return full string
return total;
}
}
The usage will be something like this:
new RestRequest("myserver.com/rest/somewebservice", SomeClass.class, Arrays.asList(new BasicValuePair("postParameter", "someParameterValue")));
Where SomeClass.class will be Recipe[].class in your case. Also check this question to properly handle server side errors.
Man, google is your friend! A quick search for "android json" or "android json parse" gives you some nice tutorials like this one or this here.

Categories