Parsing Json with Gson gives nullfield in object - json

i got JSON that have object inside
{
"status": "OK",
"info": null,
"data": {
"product": {
"productId": "1",
"productName": "Oreo"
}
}
i parse with
ProductResponse.java
public class ProductResponse {
#SerializedName("status")
public String status;
#SerializedName("info")
public String info;
#SerializedName("data")
public Product data;
}
Product.java
public class Product {
#SerializedName("productId")
public String productId;
#SerializedName("productName")
public String productName;
}
and in reponse i get status = "OK", info = null, and data that is product with nullfields

You've defined ProductResponse#data as a String. In the JSON, it's clearly not a string, it's an object. I know nothing about GSON, but surely that's the problem... Now you've changed the question so that data is defined as Product.
But data isn't a Product, it's an object that has a product property.
It seems like you should have
public class ProductResponseData {
#SerializeName("product")
public Product product;
}
and then change ProductResponse's data to be:
#SerializedName("data")
public ProductResponseData data;

Related

Serialize Feign Json Response to object

I've the following Json response coming from a Feign client:
{
"maxResults": 1,
"total": 5,
"isLast": false,
"values": [
{
"id": 37,
"self": "https://your-domain.atlassian.net/rest/agile/1.0/sprint/23",
"state": "active",
"name": "sprint 1",
"goal": "sprint 1 goal"
}
]
}
The feign client:
#FeignClient(name = "jira")
public interface JiraFeignClient {
#GetMapping("/rest/agile/1.0/board/{boardId}/sprint?state=active&maxResults=1")
ActiveSprintResponse getActiveSprint(#PathVariable String boardId);
}
I'd like to define the ActiveSprintResponse class in order to have the information related to the "values" property (I'm only interested in those) of the json response but I don't understand how can I easily represent it.
I would have no problems for the properties "maxResults", "total" etc... but how can easily unpack "values"? I can assume I will always have only one element in the value array.
I've tried defining it like that but it clearly does not work:
public class ActiveSprintResponse {
private final String id;
private final String self;
private final String name;
private final String goal;
public ActiveSprintResponse(String id, String self, String name, String goal) {
this.id = id;
this.self = self;
this.name = name;
this.goal = goal;
}
}
You need to define a class that represents the root JSON object. You can define a property for the values of type List then:
public class ActiveSprintResponseList {
private List<ActiveSprintResponse> values;
// (Other fields omitted for simplicity)
public void setValues(List<ActiveSprintResponse> values) {
this.values = values;
}
public List<ActiveSprintResponse> getValues() {
return values;
}
}
you then need to declare that class as return type:
#FeignClient(name = "jira")
public interface JiraFeignClient {
#GetMapping("/rest/agile/1.0/board/{boardId}/sprint?state=active&maxResults=1")
ActiveSprintResponseList getActiveSprint(#PathVariable String boardId);
}
and use it on the calling side:
ActiveSprintResponseList response = client.getActiveSprint(..);
List<ActiveSprintResponse> values = response.getValues();
// work with values

Remove Optional from JSON response if is not present

I am building my simple rest server with Spring boot. My problem is the following:
In one of the objects that I have to get through API, there is an Optional field:
public class MyObject {
.....
public String description;
public Optional<String> description2;
public MyObject (Object obj) {
description = obj.getDescription();
description2= Optional.ofNullable(obj.getDescription2());
}
......
}
When obj.getDescription2() is null, and retrieve it, in JSON format I got:
{
"description": "Lorem ipsum",
"description2": {
"present": false
}
}
What I have to do, to remove description2 from response if it's not present?
Thanks
you can use #JsonValue and #JsonCreator on methods that will output the data as you wish. for example:
#JsonValue
public String getDescription2() {
return desription2.orElse(null);
}

java.lang.NullPointerException while deserializing with gson

Hello everyone i have some trouble to deserialize my json with gson, when i try to deserialize into my List i dont catch any errors but whenever i try to display the content of the List i got a java.lang.NullPointerException.
Here is the json:
{
"_id": "577f81286ed8b475f5faf6fb",
"title": "bad (feat. vassy) [radio edit]",
"album": "Listen",
"artist": {
"_id": "577f81140e8784358e32ae2d",
"name": "david guetta"
},
"genre": {
"_id": "577f81140e8784358e32ae2e",
"name": "dance"
},
"duration": "2m50s",
"year": 2014,
"artwork": {
"small": "https://i.scdn.co/image/f59354f8d3f2841e44c1bd7aa0cd55a22843cfc7",
"medium": "https://i.scdn.co/image/9b092f765831793404d46b816d688135ff32735f",
"large": "https://i.scdn.co/image/6e94ab39c917096d876b895dbab0019953d27a96",
"default": "https://i.scdn.co/image/6e94ab39c917096d876b895dbab0019953d27a96"
},
"extraGenres": [],
"extraArtists": []
}
Here is my model:
public class SongDetails {
public String _id;
public String title;
public String album;
public String duration;
public int year;
#SerializedName("artist") Artist artist;
public static class Artist {
public String _id;
public String name;
}
#SerializedName("genre") Genre genre;
public static class Genre {
public String _id;
public String name;
}
#SerializedName("artwork") Artwork artwork;
public static class Artwork {
public String small;
public String medium;
public String large;
#SerializedName("default")
public String defaultX;
}
#SerializedName("votes") public VotesPlayer votes;
public static class VotesPlayer {
public int upVotes;
public int downVotes;
public int standing;
public String by;
}
}
I try to deserialize like this:
Gson gson = new Gson();
Log.d("playdetails to des", toDeserialize);
// toDeserialize = {"_id":"577f81286ed8b475f5faf6fb","title":"bad (feat. vassy) [radio edit]","album":"Listen","artist":{"_id":"577f81140e8784358e32ae2d","name":"david guetta"},"genre":{"_id":"577f81140e8784358e32ae2e","name":"dance"},"duration":"2m50s","year":2014,"artwork":{"small":"https://i.scdn.co/image/f59354f8d3f2841e44c1bd7aa0cd55a22843cfc7","medium":"https://i.scdn.co/image/9b092f765831793404d46b816d688135ff32735f","large":"https://i.scdn.co/image/6e94ab39c917096d876b895dbab0019953d27a96","default":"https://i.scdn.co/image/6e94ab39c917096d876b895dbab0019953d27a96"},"extraGenres":[],"extraArtists":[]}
try {
Response r = gson.fromJson(toDeserialize, Response.class);
Log.d("deser details", r.myPlaylistDetails.size()+"");
} catch (Exception e) {
e.printStackTrace();
}
public class Response {
public List<SongDetails> myPlaylistDetails;
}
I got this error
W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at the line of the : "Log.d("deser details", r.myPlaylistDetails.size()+"");"
I have replaced
Response r = gson.fromJson(toDeserialize, Response.class);
by to deserialize my json properly
SongDetails r = gson.fromJson(toDeserialize, SongDetails.class);
then display my details like this:
Log.d("deser details", r.title);

Parse a json object with multiple sub-objects inside with GSON

i have an issue with the response of an API that i want to use, i was developing an APP that consumes this API using Retrofit 1.9.0 and GSON 2.3.1.
The Json that i want to parse is like:
{
"user1": {
"id": 1,
"name": "foo",
"address": "bar"
},
"user2":{
"id": 2,
"name": "foo",
"addres":"bar"
},
... it can be any number of users ...
"userN":{
"id": N,
"name": "foo,
"address": "bar"
}
}
So i have an POJO named User:
public class User{
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
I was trying to parse that json with the configuration Map<String, User>:
Callback< <Map<String, User> > callback
But when i run it, i have a GSON error:
gson expecting array but found object
How can i parse the json in a correct way?
PD: i can't change the API response, it's an external API.
Try specifying a concrete type for you callback, like HashMap. Map is an interface.
Callback< <HashMap<String, User> > callback;
Usually you will get casting exception instead of a parsing error, but worth a try.

JsonArray and Gson

The JSON library I'm using is Gson. I'm having difficulty formulating a functioning data type to represent the following JSON string:
{
"latestoffers": [
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": "534.99",
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
},
{
"id": "4xTIQAPySG68IS0CGyOuyO",
"price": "582.41",
"firstrecorded_at": 1380725000,
"lastrecorded_at": 1382862800,
"seller": "Beach Audio",
"currency": "USD"
},
{
"id": "5nW67R2V4CwmE8cwaWsawe",
"price": "578.04",
"firstrecorded_at": 1379524200,
"lastrecorded_at": 1379998900,
"seller": "Beach Audio",
"currency": "USD"
}
],
"offers_count": 6,
"name": "newegg.com",
"recentoffers_count": 2,
"sku": "N82E16834216463",
"url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463"
}
My data class (so far) is as follows, it's the method getOfferData() that I don't how to complete. I'm also not certain whether JsonArray is the appropriate JSON element to be using?
static class LatestOffers {
Integer offers_count;
String name;
Integer recentoffers_count;
String sku;
String url;
java.util.List<JsonArray> getOfferData() {
List<JsonArray> list = new ArrayList<JsonArray>();
// how do I get parse the 'id', 'price', 'firstrecorded_at' etc. to add them to the ArrayList?
return list;
}
Integer getOffers_count() {
return offers_count;
}
String getName() {
return name;
}
Integer getRecentoffers_count() {
return recentoffers_count;
}
String getSku() {
return sku;
}
String getUrl() {
return url;
}
}
Any assistance, please? Thank you.
EDIT
Turns out I was unnecessarily complicating things, this works as intended:
static class LatestOffers {
List<Offer> latestoffers;
List<Offer> getOffer() {
return latestoffers;
}
}
static class Offer {
private String id;
private String price;
private long firstrecorded_at;
private long lastrecorded_at;
private String seller;
private String availability;
private String currency;
String getId() {
return id;
}
String getPrice() {
return price;
}
long getFirstrecorded_at() {
return firstrecorded_at;
}
long getLastrecorded_at() {
return lastrecorded_at;
}
String getSeller() {
return seller;
}
String getAvailability() {
return availability;
}
String getCurrency() {
return currency;
}
}
Thank you to all who answered, I'm accepting the answer of user2762451 as (s)he was the first to suggest the use of another class for the Offer data.
I'd advise you to make new POJO for object in array.
class Offer {
private String id;
private String price;
private long firstRecordedAt;
private long lastRecordedAt;
private String seller;
private String availability;
private String currency;
}
And your LatestOffers class can have a List<Offer> offers; and the method getOfferData() should return List<Offer>.
Basically, the following:
static class LatestOfferDetail {
private int offersCount;
private String name;
private int recentOffersCount;
private String sku;
private String url;
private List<Offer> latestOffers = new ArrayList<Offer>();
//other getters and setters
public List<Offer> getLatestOffers() {
return latestOffers;
}
}
Also, you seem to be following multiple naming conventions in the same piece of code and JSON. With JAVA, it's advisable to follow CamelCaseNaming. I've updated answer to reflect those.
Also, your getter method for latestOffers has a name different from convention. It's advisable to name it like get{FieldName}. I've updated answer to reflect that.
Create another POJO contain all parameter use in array like below :
public class MyOffer
{
private String id;
private double price;
private long firstrecorded_at;
private long lastrecorded_at;
private String seller;
private String availability;
private String currency;
//your getter and setter methods here.
}
Include List of above pojo in your class LatestOffers :
List<MyOffer> latestoffers = new ArrayList<MyOffer>();
your class LatestOffers look like this
static class LatestOffers
{
Integer offers_count;
String name;
Integer recentoffers_count;
String sku;
String url;
List<MyOffer> latestoffers = new ArrayList<MyOffer>();
//getter and setter method
}
Main Class for Test:
public static void main(String[] args) {
LatestOffers lso = new LatestOffers();
lso.setName("N82E16834216463");
lso.setOffers_count(6);
lso.setRecentoffers_count(2);
lso.setSku("N82E16834216463");
lso.setUrl("http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463");
MyOffer offer = null;
List<MyOffer> list = new ArrayList<MyOffer>();
for(int i=0;i<2;i++){
offer = new MyOffer();
offer.setAvailability("In stock. [BBX: Buy Box]");
offer.setCurrency("USD");
offer.setFirstrecorded_at(1377808800);
offer.setId("4qXleunwNMCKi8M0q0CuMa");
offer.setLastrecorded_at(1382862800);
offer.setPrice(534.99);
offer.setSeller("Newegg");
list.add(offer);
}
lso.setLatestoffers(list);
Gson gson = new Gson();
String json = gson.toJson(lso);
System.out.println(json);
}
Output :
{
"offers_count": 6,
"name": "N82E16834216463",
"recentoffers_count": 2,
"sku": "N82E16834216463",
"url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16834216463",
"latestoffers": [
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": 534.99,
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
},
{
"id": "4qXleunwNMCKi8M0q0CuMa",
"price": 534.99,
"firstrecorded_at": 1377808800,
"lastrecorded_at": 1382862800,
"seller": "Newegg",
"availability": "In stock. [BBX: Buy Box]",
"currency": "USD"
}
]
}
no need to define getOfferData() method just create list of MyOffer class and set that list into latestoffers list define in your class LatestOffers. It will serialize your list into JsonArray when you convert your POJO into JSON String.