Hi i'm making an app where user can send cards to other user but when i click send i'm trying to use url shortening to send link but my url shortening is not working at all it always shows the error message url shortening failed
I did some research on SO but did not get a proper solution
I know something is not right but dont know which part is not right
below is my code for url shortening
public void getShortenedUrl(String url, final int sendType){
try {
if (NetworkInfo.isNetworkAvailable(getActivity())) {
final boolean isMyCard=getArguments().getBoolean("isMyCard");
final String sharedTo=ceShareVia.getText().toString();
final String[] addresses = sharedTo.split(",");
LongUrl data = new LongUrl(url);
Call<LongUrl> cardResponseCall = ApiClientMain.getApiClient("https://www.googleapis.com/urlshortener/v1/")
.getShortenedUrl("application/json",ApplicationData.GOOGLE_URL_SHORTENER_KEY, data);
pbShare.setVisibility(View.VISIBLE);
cardResponseCall.enqueue(new retrofit2.Callback<LongUrl>() {
#Override
public void onResponse(Call<LongUrl> call, Response<LongUrl> response) {
pbShare.setVisibility(View.GONE);
if (response != null && response.body() != null) {
String url = response.body().getId();
String message;
if(isMyCard) {
message = "Hello," + "\n"
+ "Thanks for connecting!\n\n" + introMessage + "\n\n" + url + "\n\nRegards,\n"
+ preferenceManager.getPreferenceValues(PreferenceConstant.PERSON_NAME)
+ "\n" + "Have a nice day!";
}else {
message = "Hello," + "\n"
+ "Thanks for connecting!\n\n" + introMessageOther + "\n\n" + url + "\n\nRegards,\n"
+ preferenceManager.getPreferenceValues(PreferenceConstant.PERSON_NAME)
+ "\n" + "Have a nice day!";
}
switch (sendType){
case 0:
sendEmail(addresses,"My Business Card",message);
break;
case 1:
sendSms(sharedTo,message);
break;
case 2:
shareTextUrl(message);
break;
}
}
else {
Toast.makeText(getActivity(),"Url shortening failed",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<LongUrl> call, Throwable t) {
pbShare.setVisibility(View.GONE);
Toast.makeText(getActivity(),"Url shortening failed",Toast.LENGTH_SHORT).show();
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
and here is model class for Long Url
public class LongUrl {
#SerializedName("longUrl")
#Expose
private String longUrl;
#SerializedName("id")
#Expose
private String id;
#SerializedName("kind")
#Expose
private String kind;
public String getLongUrl() {
return longUrl;
}
public void setLongUrl(String longUrl) {
this.longUrl = longUrl;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public LongUrl(){
}
public LongUrl(String longUrl){
this.longUrl = longUrl;
}
}
Google URL Shortener is turned Down.
OFFICIAL RELEASE
Starting March 30, 2018, we will be turning down support for goo.gl URL shortener. From April 13, 2018 only existing users will be able to create short links on the goo.gl console. You will be able to view your analytics data and download your short link information in csv format for up to one year, until March 30, 2019, when we will discontinue goo.gl. Previously created links will continue to redirect to their intended destination.
Read this Blog for More Details.
If this is a New Project you cant create Shorten URL using the API
Related
I have a working Telegram bot that replies to my private messages. However, when I add it to my test chat and run the app, I get this error: 'Unexpected action from user'. I guess, it's a wrong way to create a bot for group chat, and maybe I shouldn't use TelegramLongPollingBot. Can you please help me to understand, how to create a group chat bot?
The Bot's class:
public class MessageCalculator extends TelegramLongPollingBot {
private PropertiesFileReader propertiesFileReader = new PropertiesFileReader();
private Properties prop;
{
try {
prop = propertiesFileReader.readPropertiesFile("src/main/resources/config.properties");
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
private static final Logger log = LoggerFactory.getLogger(Main.class);
private int messageCount = 0;
#Override
public String getBotUsername() {
return prop.getProperty("telegram.bot.username");
}
#Override
public String getBotToken() {
return prop.getProperty("telegram.bot.token");
}
#Override
public void onUpdateReceived(Update update) {
if (update.hasMessage() && update.getMessage().hasText()) {
String textFromUser = update.getMessage().getText();
Long userId = update.getMessage().getChatId();
String userFirstName = update.getMessage().getFrom().getFirstName();
log.info("[{}, {}] : {}", userId, userFirstName, textFromUser);
messageCount++;
SendMessage sendMessage = SendMessage.builder()
.chatId(userId.toString())
.text("Hello, " + userFirstName + "! Thank you for the message #" + messageCount ": " + textFromUser)
.build();
try {
this.sendApiMethod(sendMessage);
} catch (TelegramApiException e) {
log.error("Sending message error:\t", e);
}
} else {
//And I get this error message:
log.warn("Unexpected action from user");
}
}
}
I expect to create a chat bot that can count messages from each user later.
I made a post request method with Retrofit2 but I encountered this problem on my response.
Expected a string but was BEGIN_OBJECT at line 3 column 4 path $.SUCCESS
The response should be
{
"SUCCESS" :
{
"200" : "access granted",
"ra" : "approved",
"la" : "approved",
"ch" : "approved"
}
}
I uses this code for the post request
#POST("login")
Call<Post> createPost(#Body Post post);
And for the POJO class
public class Post {
private String anthony;
private String SUCCESS;
public Post(String name) {
this.anthony = name;
}
public String getSUCCESS() {
return SUCCESS;
}
}
For the method I use the following code
private void createPost() {
Post post = new Post("mypassword");
Call<Post> call = jsonPlaceHolderApi.createPost(post);
call.enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (!response.isSuccessful()) {
textViewResult.setText("Code: " + response.code());
return;
}
Post postResponse = response.body();
String content = "";
content += "Code: " + response.code() + "\n";
content += "S" + postResponse.getSUCCESS();
textViewResult.setText(content);
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
textViewResult.setText(t.getMessage());
}
});
}
Does anyone know what's wrong with my code? I expected to get the response inside the "SUCCESS" json object.
You expect SUCCESS to be an object in your wanted response but you have defined it as a String in your Post class. You should use an object for SUCCESS instead.
public class Post {
private String anthony;
private PostSuccess SUCCESS;
public Post(String name) {
this.anthony = name;
}
public PostSuccess getSUCCESS() {
return SUCCESS;
}
}
public class PostSuccess {
#JsonProperty("200")
private String _200;
private String ra;
private String la;
private String ch;
}
I looked at some other threads about this topic and integrated the solution it offered but it still throws the same error. this is the first time i try to call an api on android. here i want to 'GET' an array of objects. There is no stack trace since the app does not crash. i think the problem has to do with the array of questions.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.100:3000/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
Call<List<Post>> call = jsonPlaceHolderApi.getPosts();
call.enqueue(new Callback<List<Post>>() {
#Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
if (!response.isSuccessful()){
textViewResult.setText("Code: " + response.code());
return;
}
List<Post> posts = response.body();
for (Post post : posts){
String content = "";
content += "Doctor: " + post.getDoctor() + "\n";
content += "Name: " + post.getName() + "\n";
content += "Questions: " + post.getQuestions() + "\n\n";
textViewResult.append(content);
}
}
#Override
public void onFailure(Call<List<Post>> call, Throwable t) {
textViewResult.setText(t.getMessage());
}
});
here is an example of the json data:
[
{
"questions":[...],
"_id":"5f42954a7e252b48ec3564b6",
"name":"Lifestyle",
"doctor":"doctoremail#gmail.com",
"__v":0
},
{
"questions":[...],
"_id":"5f4299687e252b48ec3564b7",
"name":"Headache",
"doctor":"doctoremail#gmail.com",
"__v":0
},
{
"questions":[...],
"_id":"5f429b2f7e252b48ec3564b9",
"name":"Foot pain",
"doctor":"doctoremail#gmail.com",
"__v":0
}
]
I fixed it. the problem was that the 'questions' property in my model was of type string in stead of List String
package com.example.medlog;
import java.util.List;
public class Post {
private String name;
private String doctor;
private List<String> questions;
public String getName() {
return name;
}
public String getDoctor() {
return doctor;
}
public List<String> getQuestions() {
return questions;
}
}
This is my first post and english is not my native language, so please don't be cruel.
As i explained in the title I have a program that poll my mail with Apache Camel, and if there's a csv file in the attachments the program take it and process it. When i take the attachments from the email the method exchange.getIn().getAttachments() return an empty container, but I am pretty sure that the email is beeing readed. I am almost sure that I am not doing something regargins SSL but I don't really know what to do.
I am using Java OSGI with annotations and this bundles included:
org.apache.camel.camel-core 2.15.6
org.apache.camel.camel-mail 2.15.6
com.sun.mail.imap 1.6.0
com.sun.mail.javax.mail 1.6.0
javax.mail.api 1.6.0
The source code is on GitHub. Interesting classes are listed below:
ConfigReaderFactory take the email informations via ConfigAdmin and build the url.
#org.osgi.service.component.annotations.Component(name = "factory", property = "service.pid=it.sensorsystem.core.config.factory", configurationPolicy = ConfigurationPolicy.IGNORE)
public class ConfigReaderFactory implements ManagedServiceFactory {
private static final String DELETE_CONDITIONS = "readLock=changed&idempotent=false&noop=true&delete=true";
private static final String NON_DELETE_CONDITIONS = "noop=true";
private volatile DependencyManager dependencyManager;
private final Map<String, Component> components = new HashMap<>();
private String url;
private String name;
private int confLine;
private String endpointType;
private String ip;
private String username;
private String password;
private String folder;
private boolean delete;
private CamelService camel;
private TypeConverter converter;
private EventPublisher publisher;
private Double latitude;
private Double longitude;
private String email;
#Reference(service = TypeConverter.class)
public void setTypeConverter(TypeConverter converter) {
this.converter = converter;
}
public void unsetTypeConverter(TypeConverter converter) {
this.converter = null;
}
#Reference(service = EventPublisher.class)
public void setEventPublisher(EventPublisher publisher) {
this.publisher = publisher;
}
public void unsetEventPublisher(EventPublisher publisher) {
this.publisher = null;
}
#Reference(service = CamelService.class)
public void setCamelService(CamelService camel) {
this.camel = camel;
}
public void unsetCamelService(CamelService camel) {
this.camel = null;
}
#Override
public String getName() {
return this.getClass().getName();
}
#Override
public void updated(String pid, #SuppressWarnings("rawtypes") Dictionary props) throws ConfigurationException {
if (components.containsKey(pid)) {
return;
}
if (props != null) {
List<String> attributes = new ArrayList<>();
List<String> csvTypes = new ArrayList<>();
int count = 1;
String configurationLine;
while ((configurationLine = (String) props.get(Integer.toString(count++))) != null) {
List<String> values = Utils.getValuesFromLine(configurationLine);
attributes.add(values.size() >= 1 ? values.get(0) : TypeConverter.NAMELESS);
csvTypes.add(values.size() >= 2 ? values.get(1) : TypeConverter.NAMELESS);
}
confLine = Integer.parseInt((String) props.get(Config.CONFIG_LINE));
name = (String) props.get(Config.NAME);
initConfigParameters(props);
buildURL();
System.out.println("[URL] " + url);
try {
Map<String, Object> params = new HashMap<>();
params.put(Constants.ATTRIBUTES, attributes);
params.put(Constants.TYPES, csvTypes);
params.put(Constants.CONF_LINE, confLine);
params.put(Constants.SOURCE, name);
params.put(Constants.PUBLISHER, publisher);
params.put(Constants.CONVERTER, converter);
params.put(Constants.LATITUDE, latitude);
params.put(Constants.LONGITUDE, longitude);
params.put(Constants.ENDPOINT_TYPE, endpointType);
params.put(Constants.EMAIL, email);
Processor processor = new CSVProcessor(params);
camel.start(FrameworkUtil.getBundle(this.getClass()).getBundleContext(), processor, url);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void deleted(String pid) {
Component component = components.remove(pid);
dependencyManager.remove(component);
component.stop();
}
private void buildURL() {
url = "";
switch(endpointType) {
case Constants.FTP:
url += "ftp://" + username + "#" + ip + "/" + folder + "?";
if(!password.equals("")) {
url += "password=" + password + "&";
}
break;
case Constants.FILE:
url += "file://" + folder + "?";
break;
case Constants.EMAIL:
url += "imaps://imap.gmail.com?username="+email+"&password="+password
+"&delete=false&unseen=false&consumer.delay=100";
}
if(endpointType.equals(Constants.FTP) || endpointType.equals(Constants.FILE)) {
if (delete) {
url += DELETE_CONDITIONS;
} else {
url += NON_DELETE_CONDITIONS;
}
}
}
private void initConfigParameters(#SuppressWarnings("rawtypes") Dictionary props) {
confLine = Integer.parseInt((String) props.get(Config.CONFIG_LINE));
name = (String) props.get(Config.NAME);
endpointType = (String) props.get(Config.ENDPOINT_TYPE);
ip = (String) props.get(Config.IP_ADDRESS);
username = (String) props.get(Config.USERNAME);
password = (String) props.get(Config.PASSWORD);
folder = (String) props.get(Config.FOLDER);
email = (String) props.get(Config.EMAIL);
delete = ((String) props.get(Config.DELETE)).equals("true");
if((String) props.get(Config.LATITUDE)!=null) {
latitude = Double.parseDouble((String) props.get(Config.LATITUDE));
}
if((String) props.get(Config.LONGITUDE)!=null) {
longitude = Double.parseDouble((String) props.get(Config.LONGITUDE));
}
printParameters();
}
private void printParameters() {
System.out.println("\nStarting camel with parameters:");
System.out.println("[sensor_name]::" + name);
System.out.println("[latitude]::" + latitude);
System.out.println("[longitude]::" + longitude);
System.out.println("[endpoint_type]::" + endpointType);
if(endpointType.equals("ftp")) {
System.out.println("[ip_address]::" + ip);
System.out.println("[folder]::" + folder);
System.out.println("[user]::" + username);
System.out.println("[password]::" + password);
} else if(endpointType.equals("file")) {
System.out.println("[folder]::" + folder);
} else if(endpointType.equals("email")) {
System.out.println("[email]::" + email);
System.out.println("[password]::" + password);
}
System.out.println("[delete]::" + delete);
}
}
CSVProcessor take the attachments from the email and process the .csv files.
public class CSVProcessor implements Processor{
private List<String> attributes;
private List<String> csvTypes;
private int confLine;
private String source;
private String endpointType;
private TypeConverter converter;
private EventPublisher publisher;
private Long timestamp;
private Double latitude;
private Double longitude;
#SuppressWarnings("unchecked")
public CSVProcessor(Map<String, Object> params) {
this.attributes = (List<String>) params.get(Constants.ATTRIBUTES);
this.csvTypes = (List<String>) params.get(Constants.TYPES);
this.confLine = (int) params.get(Constants.CONF_LINE);
this.source = (String) params.get(Constants.SOURCE);
this.publisher = (EventPublisher) params.get(Constants.PUBLISHER);
this.converter = (TypeConverter) params.get(Constants.CONVERTER);
this.latitude = (Double) params.get(Constants.LATITUDE);
this.longitude = (Double) params.get(Constants.LONGITUDE);
this.endpointType = (String) params.get(Constants.ENDPOINT_TYPE);
}
#Override
public void process(Exchange exchange) throws Exception {
if(endpointType.equals(Constants.EMAIL)) {
Map<String, DataHandler> attachments = exchange.getIn().getAttachments();
System.out.println("Detected email [attachments: "+exchange.getIn().getAttachments().size()+"]");
System.out.println("[BODY]\n"+exchange.getIn().getBody(String.class));
if(exchange.getIn().hasAttachments()) {
System.out.println("Detected email attachments: "+attachments);
for(String name : attachments.keySet()) {
DataHandler dh = attachments.get(name);
String filename = dh.getName();
System.out.println("Detected email attachment with name: "+filename);
if(filename.contains(".csv")) {
processBody(exchange.getContext().getTypeConverter()
.convertTo(String.class, dh.getInputStream()));
}
}
}
} else {
processBody(exchange.getIn().getBody(String.class));
}
}
private void processBody(String body) {
int count = 1;
for(String line : Utils.getLines(body)){
if(count++>confLine){
for(IOTEvent event: processLine(line)){
publisher.publish(event);
}
}
}
}
private boolean processTimeAndPosition(String line) {
Iterator<String> valueIterator = Utils.getValuesFromLine(line).iterator();
Iterator<String> attributeIterator = attributes.iterator();
Iterator<String> typeIterator = csvTypes.iterator();
boolean systemTimestamp = true;
while(attributeIterator.hasNext()){
String attribute = attributeIterator.next();
String type = typeIterator.next();
String value = valueIterator.next();
switch(attribute.toLowerCase()){
case Constants.TIMESTAMP:
systemTimestamp = false;
timestamp = (Long) converter.convert(type, value);
break;
case Constants.LATITUDE:
latitude = (Double) converter.convert(type, value);
break;
case Constants.LONGITUDE:
longitude = (Double) converter.convert(type, value);
break;
}
}
return systemTimestamp;
}
private List<IOTEvent> processLine(String line){
Iterator<String> valueIterator = Utils.getValuesFromLine(line).iterator();
Iterator<String> attributeIterator = attributes.iterator();
Iterator<String> typeIterator = csvTypes.iterator();
List<IOTEvent> IOTEvents = new ArrayList<>();
boolean systemTimestamp = processTimeAndPosition(line);
// Resetting iterators
valueIterator = Utils.getValuesFromLine(line).iterator();
attributeIterator = attributes.iterator();
typeIterator = csvTypes.iterator();
while(attributeIterator.hasNext()){
String attribute = attributeIterator.next();
String type = typeIterator.next();
String value = valueIterator.next();
switch(attribute.toLowerCase()){
case Constants.TIMESTAMP:
case Constants.LATITUDE:
case Constants.LONGITUDE:
continue;
}
IOTEvent iotEvent = new IOTEvent();
iotEvent.setSource(source);
iotEvent.setValue(new Value(type, converter.convert(type, value)));
if(systemTimestamp) {
iotEvent.setCdate(new Date());
} else {
iotEvent.setCdate(new Date(timestamp));
}
iotEvent.setType(attribute);
iotEvent.setSystemCDate(systemTimestamp);
if(latitude!=null && longitude!=null )
iotEvent.setPoint(new Point(latitude, longitude));
IOTEvents.add(iotEvent);
}
return IOTEvents;
}
}
DefaultCamelService starts camel:
#Component(immediate=true)
public class DefaultCamelService implements CamelService{
private CamelContext camelContext=null;
#Override
public void start(BundleContext context, Processor processor, String url) throws Exception {
if(camelContext==null) {
camelContext = new OsgiDefaultCamelContext(context);
}
camelContext.addRoutes(new RouteBuilder() {
public void configure() {
from(url).process(processor);
}
});
try {
camelContext.start();
} catch(Exception e) {
System.out.println("Error connecting to endpoint:"+url);
}
}
#Override
public void stop() throws Exception {
camelContext.stop();
}
}
This is the result on console that regards email:
Connecting to MailStore: imaps://imap.gmail.com:993 (SSL enabled), folder=INBOX
Getting folder INBOX
Polling mailbox folder: imaps://imap.gmail.com:993 (SSL enabled), folder=INBOX
Configured property: peek on bean: com.sun.mail.imap.IMAPMessage#6dd74603 with value: true
Fetching 1 messages. Total 1 messages.
Processing message: messageNumber=[1], from=[Simone Colaci <sim.colaci#gmail.com>], to=[sensorsystem.csv#gmail.com], subject=[csv testing], sentDate=[Sep 14, 2017 1:15:24 PM], receivedDate=[Sep 14, 2017 1:15:45 PM]
Detected email [attachments: 0]
Close mailbox folder INBOX from imaps://imap.gmail.com:993 (SSL enabled), folder=INBOX
Please help me, remember that this is my first post and english is not my native language. I checked everything on internet.
Thank you.
Edit 1:
This is the body of the email sent by my Gmail account to sensorsystem.csv#gmail.com:
[BODY]
--94eb2c19b976cd06bd055924656c
Content-Type: multipart/alternative; boundary="94eb2c19b976cd06ba055924656a"
--94eb2c19b976cd06ba055924656a
Content-Type: text/plain; charset="UTF-8"
Hi,
this is a csv file
--94eb2c19b976cd06ba055924656a
Content-Type: text/html; charset="UTF-8"
<div dir="ltr"><div>Hi,<br></div>this is a csv file<br><div><div><div class="gmail_quote"><br><div dir="ltr"><br></div>
</div><br></div></div></div>
--94eb2c19b976cd06ba055924656a--
--94eb2c19b976cd06bd055924656c
Content-Type: text/csv; charset="US-ASCII"; name="esrlNcepRe_LonPM180_e063_990c_26e6.csv"
Content-Disposition: attachment;
filename="esrlNcepRe_LonPM180_e063_990c_26e6.csv"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_j7kc6dcl0
dGltZSxsYXRpdHVkZSxsb25naXR1ZGUsYWlyLHByZXMKVVRDLGRlZ3JlZXNfbm9ydGgsZGVncmVl
c19lYXN0LGRlZ0ssUGFzY2FscwoyMDAyLTA3LTAxVDAwOjAwOjAwWiw0Mi41LC0xNDcuNSwyODcu
MSwxMDIyNzAuMAo=
--94eb2c19b976cd06bd055924656c--
Edit 2:
Tried with latest Camel libraries listed below but result is the same:
org.apache.camel.camel-core 2.19.3
org.apache.camel.camel-mail 2.19.3
Edit 3:
Debug also give this warnings from Java Mail:
Sep 18, 2017 10:20:59 AM javax.mail.Session loadResource
WARNING: expected resource not found: /META-INF/javamail.default.providers
Sep 18, 2017 10:20:59 AM javax.mail.Session loadResource
WARNING: expected resource not found: /META-INF/javamail.default.address.map
I am trying to get some weather information from Yahoo APIs. This is my JSON:
JSON
This is my DTO:
public class forecast implements Serializable {
private static final long serialVersionUID = -520652416977871134L;
private String text;
private String high;
private String day;
private String code;
private String low;
private String date;
public forecast() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
#Override
public String toString() {
return "ClassPojo [text = " + text + ", high = " + high + ", day = "
+ day + ", code = " + code + ", low = " + low + ", date = "
+ date + "]";
}
}
I am only interested for the forecast element.
When I try to read the data de-serialized into my DTO all of them are null. I sense that I have not formatted my DTO properly.
Also, what Is the right way to map JSON to POJOs?
EDIT: this is my code for deserializing
String endpoint = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20"
+ "where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Rhodes%2C%20Gr%22)&"
+ "format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
try {
URL endpointURL = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) endpointURL
.openConnection();
connection.connect();
InputStream input = connection.getInputStream();
JsonReader reader = new JsonReader(new InputStreamReader(input));
reader.setLenient(true);
forecast response = new Gson().fromJson(reader,
forecast.class);
Log.d("forecast", response.toString());//override toString() to return all the values of the object
} catch (IOException e) {
e.printStackTrace();
}
Your JSON (which you get from Yahoo) is very complex. So it can not be easily mapped to simple POJO (but you still can write huge POJO that contains fields for all corresponding nested JSON elements).
But it is possible to parse and extract specific elements from JSON.
The code:
public static void main(String[] args) {
String endpoint = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20"
+ "where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Rhodes%2C%20Gr%22)&"
+ "format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
try {
URL endpointURL = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) endpointURL
.openConnection();
connection.connect();
InputStream input = connection.getInputStream();
JsonReader reader = new JsonReader(new InputStreamReader(input));
reader.setLenient(true);
JsonElement forecastSubObject = new JsonParser().parse(reader).
getAsJsonObject().get("query").
getAsJsonObject().get("results").
getAsJsonObject().get("channel").
getAsJsonObject().get("item").
getAsJsonObject().get("forecast");
System.out.println(forecastSubObject.toString());
List<forecast> forecasts = (List<forecast>)new Gson().fromJson(forecastSubObject, List.class);
System.out.println("forecast : " + forecasts);
System.out.println("first forecast: " + forecasts.get(0));
} catch (IOException e) {
e.printStackTrace();
}
}
Using JsonParser you can walk through elements (by theirs names). When 'forecast' element is reached corresponding string is extracted. Then it parsed as usual object and mapped to list of your forecast POJO.
Generally speaking mapping to/from JSON is very wide sphere. Different libraries provide different ways for achieving this (from simple and dirty to complex but reliable).