Jackson deserialization error: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field - java

The I am getting the above exception on a model which does contain the field. The exception also appears to be sporadic which is further cause for concern. I certainly can wrap the class with
JsonIgnoreProperties(ignoreUnknown = true)
But certainly will not want to do this.
The model is as follows:
public class OrderCommand {
private int orderId;
private String item;
private int numberOfItems;
private double price;
private Payment payment;
private String[] packages;
private List<Shipment> shipment;
private String orderStatus;
public OrderCommand(){}
public OrderCommand(String item, int numberOfItems, double price, OffsetDateTime timeStamp) {
this.item = item;
this.numberOfItems = numberOfItems;
this.price = price;
orderId = timeStamp.getNano();
}
public OrderCommand setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
return this;
}
public String getOrderStatus(){
return this.orderStatus;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getNumberOfItems() {
return numberOfItems;
}
public void setNumberOfItems(int numberOfItems) {
this.numberOfItems = numberOfItems;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public void setPackages(String[] packages) {
this.packages = packages;
}
public String[] getPackages(){
return packages;
}
public void setShipment(List<Shipment> shipment) {
this.shipment = shipment;
}
public List<Shipment> getShipment(){
return this.shipment;
}
public String toString(){
return ReflectionToStringBuilder.toString(this);
}
public Payment getPayment() {
return payment;
}
public OrderCommand setPayment(Payment payment) {
this.payment = payment;
return this;
}
}
and the offending JSON is:
{
"item": "headphones",
"price": 200.0,
"orderId": 600000000,
"payment": {
"charge": 200.0,
"paymentMethod": "VISA",
"success": true,
"failureReason": null,
"accountNumber": "1234"
},
"packages": [
"headphones.package0",
"headphones.package1"
],
"shipment": null,
"orderStatus": "PAYMENT-RECEIVED",
"numberOfItems": 2
}
How do I prevent this from happening and get deserialization happening reliably?
EDIT 1:
The exception indicates that the payment field is not recognized. The payment class is:
public class Payment {
private double charge;
private String paymentMethod;
private boolean success;
private String failureReason;
private String accountNumber;
public double getCharge() {
return charge;
}
public Payment setCharge(double charge) {
this.charge = charge;
return this;
}
public String getPaymentMethod() {
return paymentMethod;
}
public Payment setPaymentMethod(String paymentMethod) {
this.paymentMethod = paymentMethod;
return this;
}
public boolean getSuccess() {
return success;
}
public Payment setSuccess(boolean success) {
this.success = success;
return this;
}
public String getFailureReason() {
return failureReason;
}
public Payment setFailureReason(String failureReason) {
this.failureReason = failureReason;
return this;
}
public String getAccountNumber() {
return accountNumber;
}
public Payment setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
return this;
}
}
EDIT 2
Full exception is as follows:
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field \"payment\" (class com.sailpoint.rss.rss_service.model.OrderCommand), not marked as ignorable (8 known properties: \"numberOfItems\", \"item\", \"orderId\", \"shipment\", \"packages\", \"orderProcessingTime\", \"orderProcessed\", \"price\"])
at [Source: (String)\"{\"item\":\"headphones\",\"price\":200.0,\"orderId\":36000000,\"payment\":{\"charge\":200.0,\"paymentMethod\":\"VISA\",\"success\":true,\"failureReason\":null,\"accountNumber\":\"1234\"},\"packages\":null,\"shipment\":null,\"orderStatus\":\"PAYMENT-RECEIVED\",\"numberOfItems\":2}\"; line: 1, column: 66] (through reference chain: com.sailpoint.rss.rss_service.model.OrderCommand[\"payment\"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:823)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1153)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
at io.zeebe.client.impl.ZeebeObjectMapper.fromJson(ZeebeObjectMapper.java:36)
Did not also mention but happens sporadically.

My experienced guess (in the absence of more details) is that the problem is with either orderStatus or payment because both setOrderStatus and setPayment return a value and not void.
Jackson cares about such things so I recommend annotating both methods with #JsonSetter.
The problem could also be with payment but it is impossible to tell since you didn't say which field could not be deserialized and you also didn't post the source code for the Payment class.

Related

Iterating/Getting JSONObject inside of JSONArray without key

Need to get the Every JSONObject inside this JSONArray. Currently there is only 2 JSONObjects are there but there will be more in the future. So, i need to make it dynamic based on length of the JSONArray.
Here is the whole JSON:
{
"data": [
{
"previous_class_percentage": 58.0,
"speech_disabilty": true,
"hearing_difficulty": false,
"last_name": "Krishnana",
"weight": 54.0,
"submitted_timestamp": "2018-02-15T10:22:00Z",
"id_number": "VS017BH0004"
},
{
"previous_class_percentage": 88.0,
"speech_disabilty": true,
"hearing_difficulty": false,
"last_name": "Krishnana",
"weight": 54.0,
"submitted_timestamp": "2018-02-14T10:22:00Z",
"id_number": "VS017BH0006"
}
]
}
I am trying something like this
try {
int k = 0;
while (i<sectionJsonArr.length()){
JSONObject data = sectionJsonArr.optJSONObject(k);
Log.d("json-array",data+"");
String b_certificate_no = data.getString("id_number");
if (student_birth_certfct_number.equals(b_certificate_no)){
Log.d("text","inside if");
//TO-DO CODE
}
k++;
}
}catch (JSONException e){
e.printStackTrace();
}
try{
for( int i=0; i < sectionJsonArr.length(); i++){
JSONObject data = obj.optJSONObject(i);
Log.d("json-array",data+"");
String b_certificate_no = data.getString("id_number");
if (student_birth_certfct_number.equals(b_certificate_no)){
Log.d("text","inside if");
//TO-DO CODE
}
}
}catch(JSONException e){
e.printStackTrace();
}
this is also a way to do that
Step-1: integrate below the library.
implementation 'com.google.code.gson:gson:2.8.5'
Step-2: copy below POJO class.
public class Example {
#SerializedName("data")
#Expose
private ArrayList<Datum> data = null;
public ArrayList<Datum> getData() {
return data;
}
public void setData(ArrayList<Datum> data) {
this.data = data;
}
public class Datum {
#SerializedName("previous_class_percentage")
#Expose
private Double previousClassPercentage;
#SerializedName("speech_disabilty")
#Expose
private Boolean speechDisabilty;
#SerializedName("hearing_difficulty")
#Expose
private Boolean hearingDifficulty;
#SerializedName("last_name")
#Expose
private String lastName;
#SerializedName("weight")
#Expose
private Double weight;
#SerializedName("submitted_timestamp")
#Expose
private String submittedTimestamp;
#SerializedName("id_number")
#Expose
private String idNumber;
public Double getPreviousClassPercentage() {
return previousClassPercentage;
}
public void setPreviousClassPercentage(Double previousClassPercentage) {
this.previousClassPercentage = previousClassPercentage;
}
public Boolean getSpeechDisabilty() {
return speechDisabilty;
}
public void setSpeechDisabilty(Boolean speechDisabilty) {
this.speechDisabilty = speechDisabilty;
}
public Boolean getHearingDifficulty() {
return hearingDifficulty;
}
public void setHearingDifficulty(Boolean hearingDifficulty) {
this.hearingDifficulty = hearingDifficulty;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public String getSubmittedTimestamp() {
return submittedTimestamp;
}
public void setSubmittedTimestamp(String submittedTimestamp) {
this.submittedTimestamp = submittedTimestamp;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
}
}
Step-3: Parse response.
// "response" String that you will get from server or other.
Example example = new Gson().fromJson(response,Example.class);
for (Example.Datum response: example.getData()) {
String b_certificate_no = response.getIdNumber();
}

Mapping a nested JSON response obtained using RxJava and Retrofit

I starting out with RxJava and Retrofit and wanted to create a simple app to show a list of 100 cryptocurrencies.
I am making an api call which results in something like this :
{
"Response": "Success",
"Message": "Coin list succesfully returned!",
"BaseImageUrl": "https://www.cryptocompare.com",
"BaseLinkUrl": "https://www.cryptocompare.com",
"Data": {
"LTC": {
"Id": "3808",
"Url": "/coins/ltc/overview",
"ImageUrl": "/media/19782/ltc.png",
"Name": "LTC",
"CoinName": "Litecoin",
"FullName": "Litecoin (LTC)",
"Algorithm": "Scrypt",
"ProofType": "PoW",
"SortOrder": "2"
}
...
},
"Type": 100
}
But all I want from this is "Response" and "Data". Since it is not practical to create a 100 different model classes for each coin, I want to store information of all the coins in a common class named Coin which would look something like this :
public class Coins {
#SerializedName("Algorithm")
private String mAlgorithm;
#SerializedName("CoinName")
private String mCoinName;
#SerializedName("FullName")
private String mFullName;
#SerializedName("FullyPremined")
private String mFullyPremined;
#SerializedName("Id")
private String mId;
#SerializedName("ImageUrl")
private String mImageUrl;
#SerializedName("Name")
private String mName;
#SerializedName("PreMinedValue")
private String mPreMinedValue;
#SerializedName("ProofType")
private String mProofType;
#SerializedName("SortOrder")
private String mSortOrder;
#SerializedName("Sponsored")
private Boolean mSponsored;
#SerializedName("Symbol")
private String mSymbol;
#SerializedName("TotalCoinSupply")
private String mTotalCoinSupply;
#SerializedName("TotalCoinsFreeFloat")
private String mTotalCoinsFreeFloat;
#SerializedName("Url")
private String mUrl;
public String getAlgorithm() {
return mAlgorithm;
}
public void setAlgorithm(String Algorithm) {
mAlgorithm = Algorithm;
}
public String getCoinName() {
return mCoinName;
}
public void setCoinName(String CoinName) {
mCoinName = CoinName;
}
public String getFullName() {
return mFullName;
}
public void setFullName(String FullName) {
mFullName = FullName;
}
public String getFullyPremined() {
return mFullyPremined;
}
public void setFullyPremined(String FullyPremined) {
mFullyPremined = FullyPremined;
}
public String getId() {
return mId;
}
public void setId(String Id) {
mId = Id;
}
public String getImageUrl() {
return mImageUrl;
}
public void setImageUrl(String ImageUrl) {
mImageUrl = ImageUrl;
}
public String getName() {
return mName;
}
public void setName(String Name) {
mName = Name;
}
public String getPreMinedValue() {
return mPreMinedValue;
}
public void setPreMinedValue(String PreMinedValue) {
mPreMinedValue = PreMinedValue;
}
public String getProofType() {
return mProofType;
}
public void setProofType(String ProofType) {
mProofType = ProofType;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String SortOrder) {
mSortOrder = SortOrder;
}
public Boolean getSponsored() {
return mSponsored;
}
public void setSponsored(Boolean Sponsored) {
mSponsored = Sponsored;
}
public String getSymbol() {
return mSymbol;
}
public void setSymbol(String Symbol) {
mSymbol = Symbol;
}
public String getTotalCoinSupply() {
return mTotalCoinSupply;
}
public void setTotalCoinSupply(String TotalCoinSupply) {
mTotalCoinSupply = TotalCoinSupply;
}
public String getTotalCoinsFreeFloat() {
return mTotalCoinsFreeFloat;
}
public void setTotalCoinsFreeFloat(String TotalCoinsFreeFloat) {
mTotalCoinsFreeFloat = TotalCoinsFreeFloat;
}
public String getUrl() {
return mUrl;
}
public void setUrl(String Url) {
mUrl = Url;
}
}
So finally my mapped response class would look like :
public class CoinsListResponse {
private boolean success;
private List<Coins> coinsList;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public List<Coins> getCoinsList() {
return coinsList;
}
public void setCoinsList(List<Coins> coinsList) {
this.coinsList = coinsList;
}
}
I haven't added #Serialized notations because I don't know what key to annotate it with.
My Retrofit service interface has a method to return the results to this map :
public interface CoinService {
#NonNull
#POST
Observable<CoinsListResponse> getCoinList();
}
Since, I am a starter with Retrofit and RxAndroid, there might be a better method to do this, which I am not aware of. If so, please mention that as well !! I am trying to get my head around this for days but couldn't find any answer on SO as well.
Please Help !!
Change
private List<Coins> coinsList;
to
#SerializedName("Data")
private Map<String, Coins> coinsByName;
You can then either just use coinsByName.values() or call e.g. coinsByName.get("LTC")

Java - not able to load json string to object, every element is null

I am trying to load this test json string into an object using Gson but every element carries null. There is no exception triggered during the conversion. Please let me know what I might be doing wrong.
Appreciate your help.
I am writing a longer comment here only because it is throwing an error for not writing enough text to ask my query. I can't imagine why it would do such checks.
String testSeg1 = "{\"FlightSegment\":{\"discount\":0,\"childTaxBreakup\":\"0,0,0\",\"adultTaxBreakup\":\"0,154,413\",\"viaFlight\":\"\",\"airportTaxInfant\":0,\"OperatingAirlineFlightNumber\":144,\"StopQuantity\":0,\"BookingClass\":{\"Availability\":9,\"ResBookDesigCode\":\"S\"},\"AirEquipType\":\"77W\",\"RPH\":\"\",\"airportTax\":567,\"airportTaxChild\":0,\"OperatingAirlineCode\":\"AI\",\"DepartureDateTime\":\"2017-11-27T17:00:00\",\"ArrivalDateTime\":\"2017-11-27T19:10:00\",\"imageFileName\":\"http://live.arzoo.com/FlightWS/image/AirIndia.gif\",\"FlightNumber\":144,\"airLineName\":\"Air India\",\"DepartureAirportCode\":\"BOM\",\"octax\":0,\"ArrivalAirportCode\":\"DEL\",\"BookingClassFare\":{\"bookingclass\":\"S\",\"adultFare\":3955,\"commissionOnTCharge\":0,\"farebasiscode\":\"glW5J3cLgtM=\",\"Rule\":\"This fare is Non Refundable <br> Baggage : 25K<br>Booking Class : S|Re-Schedule Charges: Rs. 750 per sector + Fare difference (If any) +admin fee 500 + Service Fee of Rs. 250 Sector .|Cancellation Charges : Basic fare +Airline administration fee 500 + Service Charges 250 Per Passenger Per Sector .\\t\\t\\t\\t\\t |\",\"adultCommission\":0,\"childCommission\":0,\"classType\":\"Economy\"},\"infantTaxBreakup\":\"0,0,0\"}}";
Type testlistType = new TypeToken<FlightSegment>(){}.getType();
FlightSegment testFlt = gson.fromJson(testSeg1, testlistType);
public class FlightSegment {
#SerializedName("Discount")
#Expose
private String discount;
#SerializedName("AirEquipType")
#Expose
private String airEquipType;
#SerializedName("ArrivalAirportCode")
#Expose
private String arrivalAirportCode;
#SerializedName("ArrivalDateTime")
#Expose
private String arrivalDateTime;
#SerializedName("DepartureAirportCode")
#Expose
private String departureAirportCode;
#SerializedName("DepartureDateTime")
#Expose
private String departureDateTime;
#SerializedName("FlightNumber")
#Expose
private String flightNumber;
#SerializedName("OperatingAirlineCode")
#Expose
private String operatingAirlineCode;
#SerializedName("OperatingAirlineFlightNumber")
#Expose
private String operatingAirlineFlightNumber;
#SerializedName("RPH")
#Expose
private String rPH;
#SerializedName("StopQuantity")
#Expose
private String stopQuantity;
#SerializedName("airLineName")
#Expose
private String airLineName;
#SerializedName("airportTax")
#Expose
private String airportTax;
#SerializedName("imageFileName")
#Expose
private String imageFileName;
#SerializedName("viaFlight")
#Expose
private String viaFlight;
#SerializedName("airportTaxChild")
#Expose
private String airportTaxChild;
#SerializedName("airportTaxInfant")
#Expose
private String airportTaxInfant;
#SerializedName("adultTaxBreakup")
#Expose
private String adultTaxBreakup;
#SerializedName("childTaxBreakup")
#Expose
private String childTaxBreakup;
#SerializedName("infantTaxBreakup")
#Expose
private String infantTaxBreakup;
#SerializedName("octax")
#Expose
private String octax;
#SerializedName("BookingClass")
#Expose
private BookingClass bookingClass;
#SerializedName("BookingClassFare")
#Expose
private BookingClassFare bookingClassFare;
public String getAirEquipType() {
return airEquipType;
}
public void setAirEquipType(String airEquipType) {
this.airEquipType = airEquipType;
}
public String getArrivalAirportCode() {
return arrivalAirportCode;
}
public void setArrivalAirportCode(String arrivalAirportCode) {
this.arrivalAirportCode = arrivalAirportCode;
}
public String getArrivalDateTime() {
return arrivalDateTime;
}
public void setArrivalDateTime(String arrivalDateTime) {
this.arrivalDateTime = arrivalDateTime;
}
public String getDepartureAirportCode() {
return departureAirportCode;
}
public void setDepartureAirportCode(String departureAirportCode) {
this.departureAirportCode = departureAirportCode;
}
public String getDepartureDateTime() {
return departureDateTime;
}
public void setDepartureDateTime(String departureDateTime) {
this.departureDateTime = departureDateTime;
}
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getOperatingAirlineCode() {
return operatingAirlineCode;
}
public void setOperatingAirlineCode(String operatingAirlineCode) {
this.operatingAirlineCode = operatingAirlineCode;
}
public String getOperatingAirlineFlightNumber() {
return operatingAirlineFlightNumber;
}
public void setOperatingAirlineFlightNumber(String operatingAirlineFlightNumber) {
this.operatingAirlineFlightNumber = operatingAirlineFlightNumber;
}
public String getRPH() {
return rPH;
}
public void setRPH(String rPH) {
this.rPH = rPH;
}
public String getStopQuantity() {
return stopQuantity;
}
public void setStopQuantity(String stopQuantity) {
this.stopQuantity = stopQuantity;
}
public String getAirLineName() {
return airLineName;
}
public void setAirLineName(String airLineName) {
this.airLineName = airLineName;
}
public String getAirportTax() {
return airportTax;
}
public void setAirportTax(String airportTax) {
this.airportTax = airportTax;
}
public String getImageFileName() {
return imageFileName;
}
public void setImageFileName(String imageFileName) {
this.imageFileName = imageFileName;
}
public String getViaFlight() {
return viaFlight;
}
public void setViaFlight(String viaFlight) {
this.viaFlight = viaFlight;
}
public BookingClass getBookingClass() {
return bookingClass;
}
public void setBookingClass(BookingClass bookingClass) {
this.bookingClass = bookingClass;
}
public BookingClassFare getBookingClassFare() {
return bookingClassFare;
}
public void setBookingClassFare(BookingClassFare bookingClassFare) {
this.bookingClassFare = bookingClassFare;
}
public String getDiscount() {
return discount;
}
public void setDiscount(String discount) {
this.discount = discount;
}
public String getAirportTaxChild() {
return airportTaxChild;
}
public void setAirportTaxChild(String airportTaxChild) {
this.airportTaxChild = airportTaxChild;
}
public String getAirportTaxInfant() {
return airportTaxInfant;
}
public void setAirportTaxInfant(String airportTaxInfant) {
this.airportTaxInfant = airportTaxInfant;
}
public String getAdultTaxBreakup() {
return adultTaxBreakup;
}
public void setAdultTaxBreakup(String adultTaxBreakup) {
this.adultTaxBreakup = adultTaxBreakup;
}
public String getChildTaxBreakup() {
return childTaxBreakup;
}
public void setChildTaxBreakup(String childTaxBreakup) {
this.childTaxBreakup = childTaxBreakup;
}
public String getInfantTaxBreakup() {
return infantTaxBreakup;
}
public void setInfantTaxBreakup(String infantTaxBreakup) {
this.infantTaxBreakup = infantTaxBreakup;
}
public String getOctax() {
return octax;
}
public void setOctax(String octax) {
this.octax = octax;
}
}
This is the JSON String -
{"FlightSegment":{"discount":0,"childTaxBreakup":"0,0,0","adultTaxBreakup":"0,154,413","viaFlight":"","airportTaxInfant":0,"OperatingAirlineFlightNumber":144,"StopQuantity":0,"BookingClass":{"Availability":9,"ResBookDesigCode":"S"},"AirEquipType":"77W","RPH":"","airportTax":567,"airportTaxChild":0,"OperatingAirlineCode":"AI","DepartureDateTime":"2017-11-27T17:00:00","ArrivalDateTime":"2017-11-27T19:10:00","imageFileName":"http://live.arzoo.com/FlightWS/image/AirIndia.gif","FlightNumber":144,"airLineName":"Air India","DepartureAirportCode":"BOM","octax":0,"ArrivalAirportCode":"DEL","BookingClassFare":{"bookingclass":"S","adultFare":3955,"commissionOnTCharge":0,"farebasiscode":"glW5J3cLgtM=","Rule":"This fare is Non Refundable <br> Baggage : 25K<br>Booking Class : S|Re-Schedule Charges: Rs. 750 per sector + Fare difference (If any) +admin fee 500 + Service Fee of Rs. 250 Sector .|Cancellation Charges : Basic fare +Airline administration fee 500 + Service Charges 250 Per Passenger Per Sector .ttttt |","adultCommission":0,"childCommission":0,"classType":"Economy"},"infantTaxBreakup":"0,0,0"}}
Don't use TypeToken because your are not loading a List of Objects, use the class directly :
FlightSegment testFlt = gson.fromJson(testSeg1, FlightSegment.class);

Jackson: Serialise ArrayList not working?

I am referring to this example here to serialize my object.
I have this initially and it works.
public class MyClass implements Serializable {
private String mediaitem_id;
private String customer_id;
private int quantity;
public MyClass(String item, String customer, int quantity){
this.mediaitem_id = item;
this.customer_id = customer;
this.quantity = quantity;
}
public String toJson(){
ObjectMapper mapper = new ObjectMapper();
try{
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
return mapper.writeValueAsString(this);
}catch(Exception ex){
log.error("Error converting MyClass to json " + this, ex);
}
return "";
}
}
MyClass myClass = new MyClass("1234", "23234", 5);
myClass.toJson() gives the below, which is what I want:
{ mediaitem_id: '1234', customer_id: '23234', quantity: 5 }
But now I need to add an arraylist to the class and need to serialise it as well, so I add a new class Account:
public static class Account implements Serializable {
public String accountname;
public String accountid;
public Account(String accountname, String accountid) {
this.accountname = accountname;
this.accountid = accountid;
}
}
public class MyClass implements Serializable {
private String mediaitem_id;
private String customer_id;
private int quantity;
private List<Account> accounts = new ArrayList<>();
public MyClass(String item, String customer, int quantity){
this.mediaitem_id = item;
this.customer_id = customer;
this.quantity = quantity;
}
public void addAccount(String accountname, String accountid) {
Account anAccount = new Account(accountname, accountid);
accounts.add(anAccount);
}
public String toJson(){
ObjectMapper mapper = new ObjectMapper();
try{
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
return mapper.writeValueAsString(this);
}catch(Exception ex){
log.error("Error converting MyClass to json " + this, ex);
}
return "";
}
}
MyClass myClass = new MyClass("1234", "23234", 5);
myClass.addAccount("acc-01", "a001");
myClass.addAccount("acc-02", "a002");
myClass.toJson() still gives the same:
{ mediaitem_id: '1234', customer_id: '23234', quantity: 5 }
What am I missing now?
I wanted to get something like:
{ mediaitem_id: '1234', customer_id: '23234', quantity: 5, accounts: [{accountname: 'acc-01', accountid: 'a001'}, {accountname: 'acc-02', accountid: 'a002'}]}
I recommed add your getter and setter for all property in your MyClass .
public String getMediaitem_id() {
return mediaitem_id;
}
public void setMediaitem_id(String mediaitem_id) {
this.mediaitem_id = mediaitem_id;
}
public String getCustomer_id() {
return customer_id;
}
public void setCustomer_id(String customer_id) {
this.customer_id = customer_id;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}

Parse Json array with multiple objects using retrofit 2 in android

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/

Categories