I'm trying to populate a JTable with POJOS that I've extracted using Gson(). Using the debugger, or by printing the values to the console using toString(), I can see that the mapping of the objects was successful. My problem lies with populating my custom Jtable with the objects.
Problem: My GUI contains a button that takes a search field, and sends it to an API which returns a response in JSON, which I map correctly but I do not know how to get the data into the table.
What I've tried: The addFilings() and insertFilings() methods return: The method addFilings(Filing) in the type FilingsTableModel is not applicable for the arguments (ExtractorClass)
Codes
Here is the Filing Class with getters and setters and toString() method:
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Filing {
#SerializedName("id")
#Expose
private static String id;
#SerializedName("filing_date")
#Expose
private FilingDate filingDate;
#SerializedName("accepted_date")
#Expose
private AcceptedDate acceptedDate;
#SerializedName("period_end_date")
#Expose
private PeriodEndDate periodEndDate;
#SerializedName("report_type")
#Expose
private String reportType;
#SerializedName("sec_unique_id")
#Expose
private String secUniqueId;
#SerializedName("filing_url")
#Expose
private String filingUrl;
#SerializedName("report_url")
#Expose
private String reportUrl;
public String getId() {
return id;
}
public void setId(String id) {
Filing.id = id;
}
public FilingDate getFilingDate() {
return filingDate;
}
public void setFilingDate(FilingDate filingDate) {
this.filingDate = filingDate;
}
public AcceptedDate getAcceptedDate() {
return acceptedDate;
}
public void setAcceptedDate(AcceptedDate acceptedDate) {
this.acceptedDate = acceptedDate;
}
public PeriodEndDate getPeriodEndDate() {
return periodEndDate;
}
public void setPeriodEndDate(PeriodEndDate periodEndDate) {
this.periodEndDate = periodEndDate;
}
public String getReportType() {
return reportType;
}
public void setReportType(String reportType) {
this.reportType = reportType;
}
public String getSecUniqueId() {
return secUniqueId;
}
public void setSecUniqueId(String secUniqueId) {
this.secUniqueId = secUniqueId;
}
public String getFilingUrl() {
return filingUrl;
}
public void setFilingUrl(String filingUrl) {
this.filingUrl = filingUrl;
}
public String getReportUrl() {
return reportUrl;
}
public void setReportUrl(String reportUrl) {
this.reportUrl = reportUrl;
}
public String toString() {
return "[id: " + id + ", Filing Date: " + filingDate.year + "/" + filingDate.month + "/" + filingDate.day
+ ", report_type: " + reportType + ", Report url: " + reportUrl + "]";
}
}
Here is the Extractor class to map the objects:
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ExtractorClass {
#SerializedName("filings")
#Expose
private List<Filing> filings = null;
#SerializedName("company")
#Expose
private Company company;
#SerializedName("next_page")
#Expose
private String nextPage;
public List<Filing> getFilings() {
return filings;
}
public void setFilings(List<Filing> filings) {
this.filings = filings;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getNextPage() {
return nextPage;
}
public void setNextPage(String nextPage) {
this.nextPage = nextPage;
}
}
Here is the JButton in the main application window:
JButton btnNewButton = new JButton("Search");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
ApiKeyAuth auth = (ApiKeyAuth) defaultClient.getAuthentication("ApiKeyAuth");
auth.setApiKey("API_KEY");
// String identifier = "AAPL"; // String | A Company identifier (Ticker,
// CIK, LEI, Intrinio ID)
String reportType = null; // String | Filter by report type [see -
// /documentation/sec_filing_report_types]. Separate values with commas to
// return multiple report types.
LocalDate startDate = null; // LocalDate | Filed on or after the given date
LocalDate endDate = null; // LocalDate | Filed before or after the given date
Integer pageSize = 50; // Integer | The number of results to return
String nextPage = null; // String | Gets the next page of data from a previous API call
String userInput = null;
CompanyApi companyApi = new CompanyApi();
userInput = textField.getText().trim().toUpperCase();
String identifier = userInput;
try {
ApiResponseCompanyFilings result = companyApi.getCompanyFilings(identifier, reportType, startDate,
endDate, pageSize, nextPage);
String convertedResult = new Gson().toJson(result);
ExtractorClass extractedObjects = new Gson().fromJson(convertedResult, ExtractorClass.class);
model.addFilings(extractedObjects);
} catch (ApiException e) {
System.err.println("Exception when calling CompanyApi#getCompanyFilings");
e.printStackTrace();
}
}
});
And finally here is the custom table:
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import com.g4ther.SECextractor.Date;
import com.g4ther.SECextractor.Filing;
import com.g4ther.SECextractor.FilingDate;
public class FilingsTableModel extends AbstractTableModel
{
private String[] columnNames =
{
"ID",
"Filing Date",
"Report Type",
"Report URL"
};
private List<Filing> filings;
public FilingsTableModel()
{
filings = new ArrayList<Filing>();
}
public FilingsTableModel(List<Filing> filings)
{
this.filings = filings;
}
public int getColumnCount()
{
return columnNames.length;
}
public String getColumnName(int column)
{
return columnNames[column];
}
public int getRowCount()
{
return filings.size();
}
#Override
public Class getColumnClass(int column)
{
switch (column)
{
case 2: return Date.class;
default: return String.class;
}
}
#Override
public boolean isCellEditable(int row, int column)
{
switch (column)
{
case 2: return true; // only the birth date is editable
default: return false;
}
}
#Override
public Object getValueAt(int row, int column)
{
Filing filing = getFiling(row);
switch (column)
{
case 0: return filing.getId();
case 1: return filing.getFilingDate();
case 2: return filing.getReportType();
case 3: return filing.getReportUrl();
default: return null;
}
}
#Override
public void setValueAt(Object value, int row, int column)
{
Filing filing = getFiling(row);
switch (column)
{
case 0: ((Filing) filing).setId((String)value); break;
case 1: ((Filing) filing).setFilingDate((FilingDate)value); break;
case 2: ((Filing) filing).setReportType((String)value); break;
case 3: ((Filing) filing).setReportUrl((String)value); break;
}
fireTableCellUpdated(row, column);
}
public Filing getFiling(int row)
{
return filings.get( row );
}
public void addFilings(Filing filing)
{
insertFilings(getRowCount(), filing);
}
public void insertFilings(int row, Filing filing)
{
filings.add(row, filing);
fireTableRowsInserted(row, row);
}
}
Original API response:
{
"filings": [
{
"id": "fil_95GBZB",
"filing_date": {
"year": 2019,
"month": 10,
"day": 30
},
"accepted_date": {
"dateTime": {
"date": {
"year": 2019,
"month": 10,
"day": 30
},
"time": {
"hour": 16,
"minute": 30,
"second": 40,
"nano": 0
}
},
"offset": {
"totalSeconds": 0
}
},
"period_end_date": {
"year": 2019,
"month": 10,
"day": 30
},
"report_type": "8-K",
"sec_unique_id": "0000320193-19-000117",
"filing_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019319000117/0000320193-19-000117-index.htm",
"report_url": "https://www.sec.gov/ix?doc\u003d/Archives/edgar/data/320193/000032019319000117/a8-kq420199282019.htm",
"instance_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019319000117/aapl-20191030.xsd"
}
],
"company": {
"id": "com_NX6GzO",
"ticker": "AAPL",
"name": "Apple Inc",
"lei": "HWUPKR0MPOU8FGXBT394",
"cik": "0000320193"
},
"next_page": "MjAxOS0xMC0zMHw1NzkxNjc1"
}
After mapping it and printing the extractedObjects to the console:
[[id: null, Filing Date: 2019/10/30, report_type: 8-K, Report url: https://www.sec.gov/ix?doc=/Archives/edgar/data/320193/000032019319000117/a8-kq420199282019.htm]]
Really stuck here, can anyone help me please?
The method addFilings(Filing) in the type FilingsTableModel is not applicable for the arguments (ExtractorClass)
First of all the method name should be addFiling(...) since the parameter is a single Filing object.
Your extractor class has the following method:
public List<Filing> getFilings()
{
return filings;
}
Which returns a List of Filing objects.
So you need to iterate through the List and invoke the addFiling(...) method for each Filing object contained in the List.
Related
I am new to Android, it's about a week that I am spending 3 hours a day on this problem but still I can not find a solution, I am going to get a list of object from server and pass them to Adapter and another process. But I got into trouble, there is no error, in my Android Studio I got " response.code = 200 " but a list of my object is empty although in Postman with same authorization and same username a list of object is not empty. I don't know what should I do, so finally I forced to ask my question hear.
First let's take a look on Postman
Body : :
Authorization : :
Now when I clicked on Send Button in Postman I got "code: 200" and hear is the response Body:
{
"results": [
{
"_id": "5c7e69d283c0b00001108fad",
"count": 2,
"productId": "5ba51d877246b700016ec205",
"username": "rezash",
"createdAt": "2019-03-05T12:21:38.196UTC",
"updatedAt": "2019-03-05T12:36:11.058UTC",
"ACL": {
"*": {
"read": true,
"write": true
}
}
},
{
"_id": "5c7e69d483c0b00001108fae",
"count": 4,
"productId": "5acc0f2c790c0c000132c984",
"username": "rezash",
"createdAt": "2019-03-05T12:21:40.338UTC",
"updatedAt": "2019-03-05T12:36:15.830UTC",
"ACL": {
"*": {
"read": true,
"write": true
}
}
}
]
}
In my OnlineShopAPI Interface:
public interface OnlineShopAPI {
String BASE_URL = "https://api.backtory.com/";
#Headers("X-Backtory-Object-Storage-Id:5a154d2fe4b03ffa0436a535")
#HTTP(method = "POST" , path = "object-storage/classes/query/Basket" , hasBody = true)
Call<MainBasketShopResponse> mainBasketShop (
#Header("Authorization") String authorization,
#Body BasketShop basketShop
);
interface getMainBasketShop {
void onResponse(List<BasketShop> basketShopList);
void onFailure(String cause);
}
}
My MainBasketShopResponse class:
public class MainBasketShopResponse {
#SerializedName("results")
List<BasketShop> basketShopList;
public MainBasketShopResponse() {
}
public List<BasketShop> getBasketShopList() {
return basketShopList;
}
public void setBasketShopList(List<BasketShop> basketShopList) {
this.basketShopList = basketShopList;
}
}
BasketShop class:
public class BasketShop {
#SerializedName("username")
private String username;
#SerializedName("productId")
private String productId;
#SerializedName("count")
private float count;
#SerializedName("createdAt")
private String createdAt;
#SerializedName("_id")
private String id;
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public BasketShop(String username) {
this.username = username;
}
public BasketShop() {
}
public BasketShop(String username, String productId, float count) {
this.username = username;
this.productId = productId;
this.count = count;
}
public BasketShop(String createdAt, String id) {
this.createdAt = createdAt;
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public float getCount() {
return count;
}
public void setCount(float count) {
this.count = count;
}
}
My Controller that contain retrofit:
public class MainBasketShopController {
OnlineShopAPI.getMainBasketShop getMainBasketShop;
public MainBasketShopController(OnlineShopAPI.getMainBasketShop getMainBasketShop) {
this.getMainBasketShop = getMainBasketShop;
}
public void start(String authorization , BasketShop basketShop){
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(OnlineShopAPI.BASE_URL)
.build();
OnlineShopAPI onlineShopAPI = retrofit.create(OnlineShopAPI.class);
Call<MainBasketShopResponse> call = onlineShopAPI.mainBasketShop(authorization , basketShop);
call.enqueue(new Callback<MainBasketShopResponse>() {
#Override
public void onResponse(Call<MainBasketShopResponse> call, Response<MainBasketShopResponse> response) {
if (response.isSuccessful()) {
Log.d("emptyhst1" , response.body().getBasketShopList().toString());
Log.d("emptyhst2" , Integer.toString(response.body().getBasketShopList().size()));
getMainBasketShop.onResponse(response.body().getBasketShopList());
}
}
#Override
public void onFailure(Call<MainBasketShopResponse> call, Throwable t) {
getMainBasketShop.onFailure(t.getMessage());
}
});
}
}
Hear is a part of my BasketShopFragment that I call MainBasketShopController with it:
MainBasketShopController mainBasketShopController = new MainBasketShopController(getMainBasketShop);
BasketShop basketShop = new BasketShop();
basketShop.setUsername(MyPreferenceManager.getInstance(getContext()).getUsername());
mainBasketShopController.start(
"bearer " + MyPreferenceManager.getInstance(getContext()).getAccessToken() ,
basketShop
);
OnlineShopAPI.getMainBasketShop getMainBasketShop = new OnlineShopAPI.getMainBasketShop() {
#Override
public void onResponse(List<BasketShop> basketShopList) {
Log.d("emptyhst3" , basketShopList.toString());
basketShopList2.clear();
basketShopList2.addAll(basketShopList);
mainBasketShopAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(String cause) {
Toast.makeText(getContext(), cause , Toast.LENGTH_SHORT).show();
}
};
I checked both of username and accessToken that i passed to the controller and I am sure that everything is looking like in Postman
After a week I found a solution , I just changed a variable "float count" to "String count" from my Model(BasketShop Class) Ops!
#SerializedName("count")
private String count;
After using http://www.jsonschema2pojo.org/ to create POJO class to convert JSON to Java Object I'm trying to get property of "distance" "inMeters" to compare them but I can't get them because it is List is there any way I can compare them
{
"originAddresses": [
"58 Oxford St, Fitzrovia, London W1D 1BH, UK"
],
"destinationAddresses": [
"109 Marylebone High St, Marylebone, London W1U 4RX, UK",
"143 Great Titchfield St, Fitzrovia, London W1W, UK",
"210 Great Portland St, Fitzrovia, London W1W 5BQ, UK",
"43-51 Great Titchfield St, Fitzrovia, London W1W 7PQ, UK"
],
"rows": [
{
"elements": [
{
"status": "OK",
"duration": {
"inSeconds": 457,
"humanReadable": "8 mins"
},
"distance": {
"inMeters": 1662,
"humanReadable": "1.7 km"
}
},
{
"status": "OK",
"duration": {
"inSeconds": 383,
"humanReadable": "6 mins"
},
"distance": {
"inMeters": 1299,
"humanReadable": "1.3 km"
}
},
{
"status": "OK",
"duration": {
"inSeconds": 376,
"humanReadable": "6 mins"
},
"distance": {
"inMeters": 1352,
"humanReadable": "1.4 km"
}
},
{
"status": "OK",
"duration": {
"inSeconds": 366,
"humanReadable": "6 mins"
},
"distance": {
"inMeters": 932,
"humanReadable": "0.9 km"
}
}
]
}
]
}
This is my Main POJO Class in the compareTo class it require int but it show only List :
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class LocationGoogle implements Comparable<LocationGoogle> {
public LocationGoogle(String originAddress, String destinationAddress,Row
rows){
super();
this.destinationAddresses = destinationAddresses;
this.originAddresses = originAddresses;
this.rows= (List<Row>) rows;
}
#SerializedName("originAddresses")
#Expose
private List<String> originAddresses = null;
#SerializedName("destinationAddresses")
#Expose
private List<String> destinationAddresses = null;
#SerializedName("rows")
#Expose
private List<Row> rows = null;
public List<String> getOriginAddresses(){
return originAddresses;
}
public void setOriginAddresses(List<String> originAddresses){
this.originAddresses = originAddresses;
}
public List<String> getDestinationAddresses(){
return destinationAddresses;
}
public void setDestinationAddresses(List<String> destinationAddresses){
this.destinationAddresses = destinationAddresses;
}
public List<Row> getRows(){
return rows;
}
public void setRows(List<Row> rows){
this.rows = rows;
}
#Override
public int compareTo(LocationGoogle compareTime){
int compare =((LocationGoogle)compareTime).getRows();
return 0;
}
}
Is JSON to Java Object is good or bad way to convert JSON to java data. Should I keep doing this or find another way?
This is class Row :
package com.example;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Row {
#SerializedName("elements")
#Expose
private List<Element> elements = null;
public List<Element> getElements() {
return elements;
}
public void setElements(List<Element> elements) {
this.elements = elements;
}
#Override
public String toString(){
return String.valueOf(elements);
}
}
This is Elements class:
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Element {
#SerializedName("status")
#Expose
private String status;
#SerializedName("duration")
#Expose
private Duration duration;
#SerializedName("distance")
#Expose
private Distance distance;
#Override
public String toString(){
return String.valueOf(distance);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Duration getDuration() {
return duration;
}
public void setDuration(Duration duration) {
this.duration = duration;
}
public Distance getDistance() {
return distance;
}
public void setDistance(Distance distance) {
this.distance = distance;
}
}
This is Duration class:
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Duration {
#SerializedName("inSeconds")
#Expose
private Integer inSeconds;
#SerializedName("humanReadable")
#Expose
private String humanReadable;
public Integer getInSeconds() {
return inSeconds;
}
public void setInSeconds(Integer inSeconds) {
this.inSeconds = inSeconds;
}
public String getHumanReadable() {
return humanReadable;
}
public void setHumanReadable(String humanReadable) {
this.humanReadable = humanReadable;
}
#Override
public String toString (){
return String.valueOf(inSeconds);
}
}
This is Distance class:
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Distance implements Comparable{
#SerializedName("inMeters")
#Expose
private Integer inMeters;
#SerializedName("humanReadable")
#Expose
private String humanReadable;
public Integer getInMeters() {
return inMeters;
}
public void setInMeters(Integer inMeters) {
this.inMeters = inMeters;
}
public String getHumanReadable() {
return humanReadable;
}
public void setHumanReadable(String humanReadable) {
this.humanReadable = humanReadable;
}
#Override
public String toString(){
return String.valueOf(inMeters);
}
#Override
public int compareTo(Object o){
int compare = ((Distance)o).getInMeters();
return compare-this.inMeters;
}
}
The code i using to compare them:
#Override
public int compareTo(LocationGoogle compareTime){
String i= getRows()
int compare =((LocationGoogle)compareTime).getRows();
return 0;
}
After seeing required int but have List i confusing.
FileReader reader = new FileReader("Path to json file");
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(reader);
System.out.println("json object = "+json.toString());
JSONArray result = (JSONArray) json.get("rows");
JSONObject result1 = (JSONObject)result.get(0);
JSONArray elements = (JSONArray) result1.get("elements");
JSONObject result2 = (JSONObject)elements.get(0);
JSONObject distance = (JSONObject)result2.get("distance");
JSONObject duration = (JSONObject)result2.get("duration");
Distance=(String)distance.get("inMeters");
use json_simple-1.0.2.jar file. It is step by step extraction.
I'm using retrofit 2 for networking functions in my project, and I'm able to parse the json object responses from the server but now I'm supposed to parse a json array that look like this
[
{
"id_asset": 1,
"id_category": 1,
"id_brand": 2,
"name": "Samsung Galaxy 6",
"status": 1,
"updated_at": "Oct 3, 2016 10:24:28 AM",
"rank": 1,
"rate": {
"id_asset_rate": 2,
"id_asset": 1,
"value": 5000,
"loan_to_value": 50,
"offered": 2500,
"annual_rate": 3,
"quantity": 5,
"created_at": "Oct 23, 2016 5:31:31 AM",
"updated_at": "Oct 23, 2016 5:32:31 AM"
},
"best_rate": {
"id_asset": "1",
"value": "5000",
"loan_to_value": "50",
"offered": "2500",
"annual_rate": "3",
"quantity": "5",
"rank": "1"
},
"category": {
"id_category": 1,
"id_parent": 0,
"name": "Mobile Phones",
"image": "",
"sort": 1,
"status": 1,
"created_at": null,
"updated_at": null,
"_links": {
"self": {
"href": "/v1/categories/1"
}
}
},
"brand": {
"id_brand": 2,
"name": "Samsung",
"status": 1,
"created_at": null,
"updated_at": null
},
"_links": {
"self": {
"href": "/v1/assets/1"
}
}
},
{
"id_asset": 2,
"id_category": 1,
"id_brand": 1,
"name": "i Phone 5",
"status": 1,
"updated_at": "Oct 3, 2016 8:04:36 AM",
"rank": false,
"rate": null,
"best_rate": false,
"category": {
"id_category": 1,
"id_parent": 0,
"name": "Mobile Phones",
"image": "",
"sort": 1,
"status": 1,
"created_at": null,
"updated_at": null,
"_links": {
"self": {
"href": "/v1/categories/1"
}
}
},
"brand": {
"id_brand": 1,
"name": "Apple",
"status": 1,
"created_at": null,
"updated_at": null
},
"_links": {
"self": {
"href": "/v1/assets/2"
}
}
}
]
This is the response from the server and I created this POJO for the response
public class AssetResponse {
private Integer id_asset;
private Integer id_category;
private Integer id_brand;
private String name;
private Integer status;
private String updated_at;
private AssetRate assetRate;
private AssetCategory assetCategory;
private Links links;
private Self self;
private AssetBrand assetBrand;
private HasLinked hasLinked;
public Integer getId_asset() {
return id_asset;
}
public void setId_asset(Integer id_asset) {
this.id_asset = id_asset;
}
public Integer getId_category() {
return id_category;
}
public void setId_category(Integer id_category) {
this.id_category = id_category;
}
public Integer getId_brand() {
return id_brand;
}
public void setId_brand(Integer id_brand) {
this.id_brand = id_brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
public AssetRate getAssetRate() {
return assetRate;
}
public void setAssetRate(AssetRate assetRate) {
this.assetRate = assetRate;
}
public AssetCategory getAssetCategory() {
return assetCategory;
}
public void setAssetCategory(AssetCategory assetCategory) {
this.assetCategory = assetCategory;
}
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
public Self getSelf() {
return self;
}
public void setSelf(Self self) {
this.self = self;
}
public AssetBrand getAssetBrand() {
return assetBrand;
}
public void setAssetBrand(AssetBrand assetBrand) {
this.assetBrand = assetBrand;
}
public HasLinked getHasLinked() {
return hasLinked;
}
public void setHasLinked(HasLinked hasLinked) {
this.hasLinked = hasLinked;
}
private class AssetRate {
private Integer id_asset_rate;
private Integer id_asset;
private Double value;
private Double loan_to_value;
private Double offered;
private Double annual_rate;
private String updated_at;
public Integer getId_asset_rate() {
return id_asset_rate;
}
public void setId_asset_rate(Integer id_asset_rate) {
this.id_asset_rate = id_asset_rate;
}
public Integer getId_asset() {
return id_asset;
}
public void setId_asset(Integer id_asset) {
this.id_asset = id_asset;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
public Double getLoan_to_value() {
return loan_to_value;
}
public void setLoan_to_value(Double loan_to_value) {
this.loan_to_value = loan_to_value;
}
public Double getOffered() {
return offered;
}
public void setOffered(Double offered) {
this.offered = offered;
}
public Double getAnnual_rate() {
return annual_rate;
}
public void setAnnual_rate(Double annual_rate) {
this.annual_rate = annual_rate;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
}
private class AssetCategory {
private Integer id_category;
private Integer id_parent;
private String name;
private String image;
private Integer sort;
private Integer status;
private String created_at;
private String updated_at;
private Links links;
public Integer getId_category() {
return id_category;
}
public void setId_category(Integer id_category) {
this.id_category = id_category;
}
public Integer getId_parent() {
return id_parent;
}
public void setId_parent(Integer id_parent) {
this.id_parent = id_parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
}
private class Links {
#SerializedName("self")
#Expose
private Self self;
/**
*
* #return
* The self
*/
public Self getSelf() {
return self;
}
/**
*
* #param self
* The self
*/
public void setSelf(Self self) {
this.self = self;
}
}
private class Self {
#SerializedName("href")
#Expose
private String href;
/**
*
* #return
* The href
*/
public String getHref() {
return href;
}
/**
*
* #param href
* The href
*/
public void setHref(String href) {
this.href = href;
}
}
private class AssetBrand {
private Integer id_brand;
private String name;
private Integer status;
private String created_at;
private String updated_at;
public Integer getId_brand() {
return id_brand;
}
public void setId_brand(Integer id_brand) {
this.id_brand = id_brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
}
private class HasLinked {
private Integer has_linked;
private Links links;
public Integer getHas_linked() {
return has_linked;
}
public void setHas_linked(Integer has_linked) {
this.has_linked = has_linked;
}
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
}
}
}
Is my pojo is right ?
My problem is, I can't parse this response. Any help will be appreciated.
Thanks in advance
EDIT :
This is my request to server (using rest api)
#GET("url")
Call<AssetResponse> getAssetList();
EDIT 2: I've changed the code to List, as suggested by Niko Adrianus Yuwono.
This is the new changes
private void getAssets() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
final ApiInterface apiInterface = retrofit.create(ApiInterface.class);
final AssetRequest assetRequest = new AssetRequest();
assetRequest.setAcc_tok(ACCESS_TOKEN);
final Call<List<AssetResponse>> assetList = apiInterface.getAssetList();
assetList.enqueue(new Callback <List<AssetResponse>>() {
#Override
public void onResponse(Call<List<AssetResponse>> call, Response<List<AssetResponse>> response) {
int statusCode = response.code();
List<AssetResponse> assetResponseList = response.body();
if (statusCode == 200) {
for (int i = 0; i < assetResponseList.size(); i++ ){
Integer id_asset = assetResponseList.get(i).getId_asset();
Integer id_category = assetResponseList.get(i).getId_category();
Integer status = assetResponseList.get(i).getStatus();
String name = assetResponseList.get(i).getName();
Log.d("Assets ","Asset id_asset bb : " + id_asset);
Log.d("Assets ","Asset id_category bb : " + id_category);
Log.d("Assets ","Asset name bb : " + name);
Log.d("Assets ","Asset status bb : " + status);
Double val = assetResponseList.get(i).getAssetRate().getValue();
Log.d("val ","val is : " +val);
}
} else {
Toast.makeText(getContext(), "network error " + statusCode, Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<List<AssetResponse>> call, Throwable t) {
Log.d("Asset GET Failure", "onFailure: " + t.getMessage());
//showProgress(false);
}
});
}
and this is the response from the server
D/Assets: Asset id_asset bb : 1 D/Assets: Asset id_category bb : 1 D/Assets: Asset name bb : Samsung Galaxy 6 D/Assets: Asset status
bb : 1 10-26 13:13:17.898 22784-22784/ D/AndroidRuntime: Shutting down
VM 10-26 13:13:17.898 22784-22784/ E/AndroidRuntime: FATAL EXCEPTION:
main Process: , PID: 22784 java.lang.NullPointerException: Attempt to
invoke virtual method 'java.lang.Double
.api.model.AssetResponse$AssetRate.getValue()' on a null object
reference
.AssetDatabaseFragment$2.onResponse(AssetDatabaseFragment.java:133)
retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
android.os.Handler.handleCallback(Handler.java:739)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:148)
android.app.ActivityThread.main(ActivityThread.java:5417)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Whenever I access the inner objects it throws error like the above
Your POJO looks right, but your JSON response is a JSONArray so you need to declare it as a List of Objects rather than an Object
#GET("url")
Call<List<AssetResponse>> getAssetList();
And you need to change your inner class access to public so GSON can see the setter and getter of that class.
Your Json key value data is changing from one index to another.
Wrong Json:
[{
//Make this either integer or boolean
"rank": 1,
// best rate is object here in the next index, it's treated as boolean.
"best_rate": {
"id_asset": "1",
"value": "5000",
"loan_to_value": "50",
"offered": "2500",
"annual_rate": "3",
"quantity": "5",
"rank": "1"
}
},
{
"rank":false,
"best_rate":false,
}
]
I have a complete project shared on github with your json.
https://github.com/lingarajsankaravelu/retrofit2v.git
Retrofit code should be like this as i mentioned in the question comment.
#GET("url")
Call<List<AssetResponse>> getAssetList();
As you have requested to explain the changes in your pojo class it should be like this.
AssetReponse.class:
public class AssetResponse {
private Integer id_asset;
private Integer id_category;
private Integer id_brand;
private String name;
private Integer status;
private String updated_at;
private AssetRate assetRate;
private AssetCategory assetCategory;
private Links links;
private Self self;
private AssetBrand assetBrand;
private HasLinked hasLinked;
public Integer getId_asset() {
return id_asset;
}
public void setId_asset(Integer id_asset) {
this.id_asset = id_asset;
}
public Integer getId_category() {
return id_category;
}
public void setId_category(Integer id_category) {
this.id_category = id_category;
}
public Integer getId_brand() {
return id_brand;
}
public void setId_brand(Integer id_brand) {
this.id_brand = id_brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
public AssetRate getAssetRate() {
return assetRate;
}
public void setAssetRate(AssetRate assetRate) {
this.assetRate = assetRate;
}
public AssetCategory getAssetCategory() {
return assetCategory;
}
public void setAssetCategory(AssetCategory assetCategory) {
this.assetCategory = assetCategory;
}
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
public Self getSelf() {
return self;
}
public void setSelf(Self self) {
this.self = self;
}
public AssetBrand getAssetBrand() {
return assetBrand;
}
public void setAssetBrand(AssetBrand assetBrand) {
this.assetBrand = assetBrand;
}
public HasLinked getHasLinked() {
return hasLinked;
}
public void setHasLinked(HasLinked hasLinked) {
this.hasLinked = hasLinked;
}
}
AssetRate.class
public class AssetRate {
private Integer id_asset_rate;
private Integer id_asset;
private Double value;
private Double loan_to_value;
private Double offered;
private Double annual_rate;
private String updated_at;
public Integer getId_asset_rate() {
return id_asset_rate;
}
public void setId_asset_rate(Integer id_asset_rate) {
this.id_asset_rate = id_asset_rate;
}
public Integer getId_asset() {
return id_asset;
}
public void setId_asset(Integer id_asset) {
this.id_asset = id_asset;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
public Double getLoan_to_value() {
return loan_to_value;
}
public void setLoan_to_value(Double loan_to_value) {
this.loan_to_value = loan_to_value;
}
public Double getOffered() {
return offered;
}
public void setOffered(Double offered) {
this.offered = offered;
}
public Double getAnnual_rate() {
return annual_rate;
}
public void setAnnual_rate(Double annual_rate) {
this.annual_rate = annual_rate;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
}
Seperate your inner class like above. Seperating your inner class model will be useful if you are working on a large project. where you don't have to write the same pojo class again. you can use this seperate class structure instead.
You can use this site to generate POJO class. Just enter your JSON response and choose which JSON type you using like GSON,Jackson.etc. and You get perfect POJO classes. no need to change anything.
http://www.jsonschema2pojo.org/
Your Retrofit interface should be
#GET("url")
Call<List<AssetReponse>> getAssessList();
And make sure that your variable name same with key on JSON Response Or you can use annotation #SerializedName for that & for make it simple you can use JSON to POJO Online converter : http://www.jsonschema2pojo.org/
I'm getting the following error when using an ObjectMapper to de-serialize an object:
JSONMappingException Can not construct instance of
org.springframework.data.Page, problem: abstract types can only be
instantiated with additional type information.
I am trying to serialize a JSON string into a Spring data object org.springframework.data.Page which represents a page of type T.
The User class is a simple POJO with first and last name. The JSON string I am deserializing is:
{
"content": [
{
"firstname": "John",
"lastname": "Doe"
},
{
"firstname": "Jane",
"lastname": "Doe"
}
],
"size": 2,
"number": 0,
"sort": [
{
"direction": "DESC",
"property": "timestamp",
"ascending": false
}
],
"totalPages": 150,
"numberOfElements": 100,
"totalElements": 15000,
"firstPage": true,
"lastPage": false
}
This causes the exception:
Page<User> userPage = (Page<User>) new ObjectMapper().mapToJavaObject(json, new TypeReference<Page<User>>(){};
Since Page is a Spring object I cannot modify it which I think makes this a bit different from the way I see this question asked elsewhere. Any thoughts?
I ended up using something like this, creating a bean as #Perception suggested:
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
public class PageImplBean<T> extends PageImpl<T> {
private static final long serialVersionUID = 1L;
private int number;
private int size;
private int totalPages;
private int numberOfElements;
private long totalElements;
private boolean previousPage;
private boolean firstPage;
private boolean nextPage;
private boolean lastPage;
private List<T> content;
private Sort sort;
public PageImplBean() {
super(new ArrayList<T>());
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getNumberOfElements() {
return numberOfElements;
}
public void setNumberOfElements(int numberOfElements) {
this.numberOfElements = numberOfElements;
}
public long getTotalElements() {
return totalElements;
}
public void setTotalElements(long totalElements) {
this.totalElements = totalElements;
}
public boolean isPreviousPage() {
return previousPage;
}
public void setPreviousPage(boolean previousPage) {
this.previousPage = previousPage;
}
public boolean isFirstPage() {
return firstPage;
}
public void setFirstPage(boolean firstPage) {
this.firstPage = firstPage;
}
public boolean isNextPage() {
return nextPage;
}
public void setNextPage(boolean nextPage) {
this.nextPage = nextPage;
}
public boolean isLastPage() {
return lastPage;
}
public void setLastPage(boolean lastPage) {
this.lastPage = lastPage;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
public Sort getSort() {
return sort;
}
public void setSort(Sort sort) {
this.sort = sort;
}
public PageImpl<T> pageImpl() {
return new PageImpl<T>(getContent(), new PageRequest(getNumber(),
getSize(), getSort()), getTotalElements());
}
}
and then modify your code to use the concrete class and get the PageImpl:
#SuppressWarnings("unchecked")
Page<User> userPage = ((PageImplBean<User>)new ObjectMapper().readValue(json, new TypeReference<PageImplBean<User>>() {})).pageImpl();
You can do this:
public class YourClass {
static class CustomPage extends PageImpl<User> {
#JsonCreator(mode = Mode.PROPERTIES)
public CustomPage(#JsonProperty("content") List<User> content, #JsonProperty("number") int page, #JsonProperty("size") int size, #JsonProperty("totalElements") long total) {
super(content, new PageRequest(page, size), total);
}
}
public Page<User> makeRequest(String json) {
Page<User> pg = new ObjectMapper().readValue(json, CustomPage.class);
return pg;
}
}
given the following json:
{ "response": {
"totalProcessingTime": "271.0",
"resultSets": {
"products": {
"firstHit": "1",
"lastHit": "10",
"totalHits": "77",
"hits": [
{
"number": "1",
"dmsubcategory": "TV, lyd og bilde",
"collection": "tilbud",
"title": "<b>TV</b> Panasonic 47 TX-LU 7ET5Y"
},
{
"number": "2",
"dmsubcategory": "TV, lyd og bilde",
"collection": "tilbud",
"title": "<b>TV</b> Panasonic 47 TX-LU 7ET5Y"
},
{
"number": "3",
"dmsubcategory": "TV, lyd og bilde",
"collection": "tilbud",
"title": "<b>TV</b> Panasonic 47 TX-LU 7ET5Y"
}
]
}
}
}
}
I'm using the following code to call jackson:
ObjectMapper mapper = new ObjectMapper();
SearchResult searchResult = mapper.readValue(new URL(jsonUrl + queryUrl), SearchResult.class);
I have ganerated POJOs for the whole hiearchy where the products class looks like:
public class Products {
public List<Hits> hits;
public String totalHits;
#JsonAnySetter
public void handleUnknown(String key, Object value) {
// do something: put to a Map; log a warning, whatever
}
public List<Hits> getHits() {
return hits;
}
public void setHits(List<Hits> hits) {
this.hits = hits;
}
public String getTotalHits() {
return totalHits;
}
public void setTotalHits(String totalHits) {
this.totalHits = totalHits;
}
}
and the hits class:
public class Hits {
public String number;
public String title;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#JsonAnySetter
public void handleUnknown(String key, Object value) {
// do something: put to a Map; log a warning, whatever
}
}
All the other properties are mapped correct, but not the list containing hits. It's all empty. How can I map this to get it right?
Thanks!
You model is not compatible.
In order to see what is going wrong, maybe it is a good idea to have some toStrings and you could easy see where the mapping is failing.
You have a Object that needs to hold a property response, that needs to hold a property resultSets that needs to hold a property products that needs to hold hits.
I implemented like this:
GeneralResponse
- Response
- ResultSets
- Products
- Hits
- number
- title
Please test following implementation:
package snippet;
public class GeneralResponse {
private Response response;
public Response getResponse() {
return response;
}
public void setResponse(Response response) {
this.response = response;
}
#Override
public String toString() {
return "GeneralResponse [response=" + response + "]";
}
}
package snippet;
public class ResultSets {
private Products products;
public Products getProducts() {
return products;
}
public void setProducts(Products products) {
this.products = products;
}
#Override
public String toString() {
return "ResultSets [products=" + products + "]";
}
}
package snippet;
import java.util.List;
import org.codehaus.jackson.annotate.JsonAnySetter;
public class Products {
public List<Hits> hits;
public String totalHits;
#JsonAnySetter
public void handleUnknown(String key, Object value) {
// do something: put to a Map; log a warning, whatever
}
public List<Hits> getHits() {
return hits;
}
public void setHits(List<Hits> hits) {
this.hits = hits;
}
public String getTotalHits() {
return totalHits;
}
public void setTotalHits(String totalHits) {
this.totalHits = totalHits;
}
#Override
public String toString() {
return "Products [hits=" + hits + ", totalHits=" + totalHits + "]";
}
}
package snippet;
import org.codehaus.jackson.annotate.JsonAnySetter;
public class Response {
private ResultSets resultSets;
public ResultSets getResultSets() {
return resultSets;
}
public void setResultSets(ResultSets resultSets) {
this.resultSets = resultSets;
}
#Override
public String toString() {
return "Response [resultSets=" + resultSets + "]";
}
#JsonAnySetter
public void handleUnknown(String key, Object value) {
// do something: put to a Map; log a warning, whatever
}
}
package snippet;
import org.codehaus.jackson.annotate.JsonAnySetter;
public class Hits {
public String number;
public String title;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#JsonAnySetter
public void handleUnknown(String key, Object value) {
// do something: put to a Map; log a warning, whatever
}
#Override
public String toString() {
return "Hits [number=" + number + ", title=" + title + "]";
}
}
after all you can do something like:
ObjectMapper om = new ObjectMapper();
Object r = om.readValue(inputStream, GeneralResponse.class);
The code looks fine. The error may be in json response
"title": "<b>TV</b> Panasonic 47”TX-LU 7ET5Y"
The backquotes after 47 and before TX, might be troublesome. Please check if you can parse this response.