"Cannot deserialize instance of" from outside API - java

I am trying make online cantor. i need to get table with currency value from outside API, exactly from that page : http://api.nbp.pl/api/exchangerates/tables/A?format=json
I want to get answer in Currency class. Could someone help me with that task ?
#Service
public class CurrentFromNBPImpl implements CurrentFromNBP {
#Override
public Currency getValueOfCurrency(String currencyCode) throws WrongCurrencyCode {
Currency currency = null;
try {
URL url = new URL("http://api.nbp.pl/api/exchangerates/tables/A?format=json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
if (connection.getResponseCode() == 404)
throw new WrongCurrencyCode(currencyCode);
InputStreamReader inputStreamReader = new InputStreamReader(connection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String jsonOutput = bufferedReader.readLine();
connection.disconnect();
ObjectMapper objectMapper = new ObjectMapper();
Currency list = objectMapper.readValue(jsonOutput, Currency.class);
System.out.println(list);
} catch (IOException e) {
e.printStackTrace();
}
assert false;
return currency;
}
}
#Data
public class Currency {
#JsonProperty("table")
private String table;
#JsonProperty("no")
private String no;
#JsonProperty("effectiveDate")
private String effectiveDate;
#JsonProperty("rates")
private List<Rate> rates = null;
}
#Data
public class Rate {
#JsonProperty("currency")
private String currency;
#JsonProperty("code")
private String code;
#JsonProperty("mid")
private Double mid;
}
log:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of com.kolej.bartosz.challenge.domain.Currency out of START_ARRAY token
at [Source: (String)"[{"table":"A","no":"062/A/NBP/2019","effectiveDate":"2019-03-28","rates":[{"currency":"bat (Tajlandia)","code":"THB","mid":0.1202},{"currency":"dolar amerykański","code":"USD","mid":3.8202},{"currency":"dolar australijski","code":"AUD","mid":2.7098},{"currency":"dolar Hongkongu","code":"HKD","mid":0.4867},{"currency":"dolar kanadyjski","code":"CAD","mid":2.8461},{"currency":"dolar nowozelandzki","code":"NZD","mid":2.6006},{"currency":"dolar singapurski","code":"SGD","mid":2.8179},{"currency":"eu"[truncated 1616 chars]; line: 1, column: 1]

Your json object that you want to deserialize is a jsonArray. You need to deserialize into a list of Currency, instead of a Currency.

You can try this
ArrayList<Currency> list = new ArrayList<>();
list = objectMapper.readValue(data, new TypeReference<ArrayList<Currency>>() {});

Related

Adding String to a list in Java

Please have a look at the below code snippet.
I had a look at some solutions provided on stackoverflow for adding String to a list.
They did not work out well in the below case.
#RequestMapping(value = "/rest/EmployeeDept/", method = RequestMethod.GET)
// ResponseEntity is meant to represent the entire HTTP response
public ResponseEntity<EmployeeDeptResponse> getDept()
{
EmployeeDeptResponse deptResponse = new EmployeeDeptResponse();
HttpStatus httpStatus;
List<EmployeeDept> employeeDeptList = new ArrayList<EmployeeDept>();
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(
"http://localhost:8082/rest/EmployeeDept/");
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null) {
employeeDeptList.add(output);
}
deptResponse.setItems(employeeDeptList);
httpClient.getConnectionManager().shutdown();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
httpStatus = HttpStatus.OK;
return new ResponseEntity<EmployeeDeptResponse>(deptResponse,httpStatus);
}
I am getting an error in the while loop as "add in list can not be applied to java.lang.String"
The list of type "EmployeeDept".The EmployeeDept class looks like this:-
package com.springboot.postrgres.model;
import java.io.Serializable;
public class EmployeeDept implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String dept;
public EmployeeDept() {
}
public EmployeeDept(int id, String dept) {
this.id = id;
this.dept = dept;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDept() {
return dept;
}
public void setDept(String name) {
this.dept = dept;
}
}
In the above code I have a list "employeeDeptList" and a string "Output".
I need to add this string to the list.
Can any of you provide suitable suggestions.
Thanks in advance.
employeeDeptList is of type ArrayList<EmployeeDept>.
List<EmployeeDept> employeeDeptList = new ArrayList<EmployeeDept>();
output on the other hand is of type String
String output;
So when you do employeeDeptList.add(output);, you are trying to add a String to your employeeDeptList, when it should be an EmployeeDept.
So you either make output an EmployeeDept or you rethink what you want to do with it.
As a suggestion, I am going to assume that your output should contain the information you need to create an EmployeeDept. You probably want to parse that information and create a EmployeeDept dept = new EmployeeDept(parsedId, parsedDept); and then add it to employeeDeptList as employeeDeptList.add(dept);
employeeDeptList is a list of EmployeeDept object. You are trying to add a String to the list of EmployeeDept. Which is not posssible unless you change the type of output variable to EmployeeDept.
If you response is a valid json (specified header), why won't you try to map it to objects?
ObjectMapper mapper = new ObjectMapper();
//assuming your response entity content is a list of objects (json array, since you specified header 'application/json'
String jsonArray = String theString = IOUtils.toString(response.getEntity().getContent(), encoding);
employeeDeptList = List<Employee> list = mapper.readValue(jsonString, TypeFactory.defaultInstance().constructCollectionType(List.class, employeeDeptList.class));
//assuming your response is a single object
String json = String theString = IOUtils.toString(response.getEntity().getContent(), encoding);
employeeDeptList.add(mapper.readValue(json, Employee.class));
//assuming every line of content is an object (does not really make sense)
BufferedReader br = new BufferedReader(ew InputStreamReader((response.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null) {
employeeDeptList.add(mapper.readValue(output, Employee.class));
}
There is a problem in your code.
while ((output = br.readLine()) != null) {
employeeDeptList.add(output);
}
output is a String and you are trying to add that to a List<EmployeeDept>. You can't do that. If you want to add output to a List, you should create a List of Strings. Something like List<String>
As you mentioned, what you are getting is,
{
"1499921014230": {
"id": 1499921014230,
"dept": "mechanics"
},
"1499921019747": {
"id": 1499921019747,
"dept": "civil"
}
}
If you can change that , you can try to change it to a simple array of objects,
[
{
"id": 1499921014230,
"dept": "mechanics"
},
{
"id": 1499921019747,
"dept": "civil"
}
]
Add below dependency if you use maven, or just add the .jar to the lib,
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
Then try something like this,
while ((output = br.readLine()) != null) {
JSONArray jsonArr = new JSONArray(output);
for (int i = 0; i < jsonArr.length(); i++) {
JSONObject jsonObj = jsonArr.getJSONObject(i);
String dept = jsonObj.getString("dept");
int id = jsonObj.getInt("id");
System.out.println("id : " + id + " dept : " + dept);
employeeDeptList.add(new EmployeeDept(id, dept));
}
}

Getting error "Expected BEGIN_OBJECT but was STRING at line 1" from a multi layer json

Here is the entire class:
public class Item {
static class Page {
Map <String,String> other_data;
Map <String,Map<String,List<Map<String,String>>>> specification;
}
public static String showName() throws Exception {
String json = Json.fetch(jsonurl);
Gson gson = new Gson();
Page result = gson.fromJson(json, Page.class);
return result.specification.get("result").get("feature").get(0).get("value");
// not working.
//return result.other_data.get("id"); <-- this one working
}
}
Here's how I fetch the json:
public class Json {
public static String fetch(String urlString) throws Exception {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(Connection.auth(urlString)));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
//return buffer.toString();
return buffer.toString();
} finally {
if (reader != null)
reader.close();
}
}
}
I have been struggling to get a specific value from a mixed-type JSON feed using gson.
{
"other_data":{"id":"150","name":"AA"},
"specification":{"result":{"feature":[{"name":"attribute A","value":"50"}]}}
}
The feed should be valid since I can get 150 from other_data
`return result.other_data.get("id");`
However I can't get the value 50 from the first object of the array feature:
return result.specification.get("result").get("feature").get(0).get("value");
I'm receiving this error:
Expected BEGIN_OBJECT but was STRING at line 1 column 37948 path $.specification.
I think the declaration Map <String,Map<String,List<Map<String,String>>>> specification; is incorrect. I did a little debugging by changing it to Map <String,Object> specification. I managed to get the stringified object
{"feature":[{"name":"attribute A","value":"50"}]}
public class Item {
static class Page {
String page_type;
String name;
Map <String,String> submit_user_data;
Map <String,Object> specification;
}
public static String showName() throws Exception {
String json = Json.fetch(jsonurl);
Gson gson = new Gson();
Page td = gson.fromJson(json, Page.class);
return td.specification.get("result").toString(); // this one works!
}
}
Would anyone tell me what's wrong with the class getting the error?
Apparently escaping the json string solves the issue:
public static void main(String args[]) {
String json = "{\"other_data\":{\"id\":\"150\",\"name\":\"AA\"},\"specification\":{\"result\":{\"feature\":[{\"name\":\"attribute A\",\"value\":\"50\"}]}}}";
Gson gson = new Gson();
Page result = gson.fromJson(json, Page.class);
System.out.println(result.specification.get("result").get("feature").get(0).get("value"));
}

Gson not deserializing JSON data

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

Errors on Json deserialize

i'm trying deserialize my object, but I can not get no error!
I'm using gson on android to read json file.
My deserialize
this is my request class, i using a rest server.
public Object getListaSeguradoras(String _codPais, String _tipoPesquisa)
{
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(Config.WS_PATH);
post.setHeader("content-type", "application/json; charset=UTF-8");
post.addHeader("Client-Application","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
//Make object in JSON format
JSONObject dato = new JSONObject();
dato.put("CodPais", _codPais);
dato.put("TipoPesquisa", _tipoPesquisa);
StringEntity entity = new StringEntity(dato.toString());
post.setEntity(entity);
HttpResponse resp = httpClient.execute(post);
String respStr = EntityUtils.toString(resp.getEntity());
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<SeguradoraLista>>(){}.getType();
Collection<SeguradoraLista> ListaSeguradoras = gson.fromJson(respStr, collectionType);
return ListaSeguradoras;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
My object:
This is my getter and setter
public class SeguradoraLista{
public String SeguradoraId;
public String Nome;
public String getSeguradoraId() {
return this.SeguradoraId;
}
public String getNome() {
return this.Nome;
}
public void setSeguradoraId ( String SeguradoraId) {
this.SeguradoraId = SeguradoraId;
}
public void setNome ( String Nome) {
this.Nome = Nome;
}
}
My json:
this is the json string on my string respStr
[{"SeguradoraId":"19","Nome":"AIG Europe"},
{"SeguradoraId":"25","Nome":"AIOI Insurance Co. Of Europe"},
{"SeguradoraId":"28","Nome":"Aktiv Forsikring A/S"},
{"SeguradoraId":"160","Nome":"Enter Forsikring AS"},
{"SeguradoraId":"167","Nome":"Euro Insurances Ltd."},
{"SeguradoraId":"189","Nome":"Försäkrings-AB Volvia"},
{"SeguradoraId":"219","Nome":"Gjensidige NOR Forsikring"},
{"SeguradoraId":"245","Nome":"If Skadeforsikring NUF"},
{"SeguradoraId":"265","Nome":"Jernbanepersonalets Forsikring Gjensiding"},
{"SeguradoraId":"271","Nome":"KLP Skadeforsikring AS"},
{"SeguradoraId":"284","Nome":"Landbruksforsikring"},
{"SeguradoraId":"309","Nome":"Lloyd's v/Vital Skade AS"},
{"SeguradoraId":"459","Nome":"SpareBank 1 Skadeforsikring AS"},
{"SeguradoraId":"472","Nome":"Tennant Forsikring nuf"},
{"SeguradoraId":"473","Nome":"Terra Skadeforsikring AS"},
{"SeguradoraId":"494","Nome":"Trygg-Hansa Forsikring Nuf"},
{"SeguradoraId":"517","Nome":"Vesta Skadeforsikring A/S"},
{"SeguradoraId":"536","Nome":"Zürich Forsikring"}]
what I'm doing wrong? I can't make this direct deserealizing?
You seem to have an array of SeguradoraLista objects.
So just create a TypeToken of type List<SeguradoraLista>
Type collectionType = new TypeToken<List<SeguradoraLista>>() {}.getType();
List<SeguradoraLista> ListaSeguradoras = gson.fromJson(respStr, collectionType);
Actually, Collection<SeguradoraLista> would work as well.

Convert Json to an specific Class

i'm trying to retrieve text from wikipedia to use on an Android app. I'm using Java.
The first thing I want to do is to retrieve the sections from an specific article, show them to the user and, when the user clicks on one section, get the section text with another http request.
So, the two requests are these:
http://en.wikipedia.org/w/api.php?format=json&action=parse&page=Valencia_Cathedral&prop=sections
and then this one:
http://en.wikipedia.org/w/api.php?format=json&action=parse&page=Valencia_Cathedral&prop=text&section=1
My question is: What kind of java objects should I create to store the information and then convert it to these classes using .fromJSON()?
Thanks to #NathanZ, I created these two classes:
public class WikiResponseSections {
String title;
List<Section> sections;
}
public class Section {
int toclevel;
String level;
String line;
String number;
String index;
String fromtitle;
int byteoffset;
String anchor;
}
But, when I convert the HTTP response to these objets by Gson, and try to read the value of the field 'title' there's an error that triggers: JavaNullPointerException.
Here's my code for the conversion:
InputStream stream = null;
try {
stream = entity.getContent();
} catch (IllegalStateException e) {
Log.e("Stream","ERROR illegalstateexception");
} catch (IOException e) {
Log.e("Stream","ERROR exception");
}
reader = new BufferedReader(new InputStreamReader(stream));
GsonBuilder bldr = new GsonBuilder();
Gson gson = bldr.create();
WikiResponse = gson.fromJson(reader, WikiResponseSections.class);
if (WikiResponse != null){
Log.i("WikiResponse",WikiResponse.getTitle()); //The error triggers HERE
publishProgress();
}
else
Log.i("WikiResponse","NULL");
}
Thanks for your help again
You can use the Google's Gson library.
It works like this:
InputStream source = ...; // your code to get the Json from a url
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
MyResponse response = gson.fromJson(reader, MyResponse.class);
Where MyResponse is your object. When you create MyResponse, give your fields the same name and type as the Json's fields
MyResponse class can be as follows:
public class MyResponse{
String title;
ArrayList<sections>;
}
public class sections{
int toclevel;
String level;
String line;
String number;
String fromtitle;
long byteoffset;
String anchor;
}
public class WikiResponseParse{
Parse parse;
public class Parse{
String title, text;
}
}
If you can't use the json fields name because it's not Java compliant:
Add the following import:
import com.google.gson.annotations.SerializedName;
and in your class:
#SerializedName("*")
public String star;

Categories

Resources