How to deserialize json with a string-url name-value pair - java

I have json response in the form
{
"total": 782,
"category": {
"id": 1120,
"name": "Computers & Programming"
},
"experts": [
{
"id": 385816,
"name": "Master Z",
"title": "Mr",
"description": " Expert in C++",
"profile": "http://...com/experts.svc/1.0/385816/..../json?.."
}
}
]
}
I am able to parse everything else in the experts[] array except "profile" whose value "http://...com/experts.svc/1.0/385816/..../json?.." has the following json response
{
"id": 385816,
"name": "Master Z",
"title": "",
"reviewsCount": 15359,
"averageRating": 4.87,
"status": 4,
"fee": 19.99,
"languages": "English",
"category": {
"id": 1120,
"name": "Computers & Programming"
}
}
The models used are as follows
1. main pojo:
public class ExpertObj
{
private String total;
private Category category;
private Experts[] experts;
}
Category pojo:
public class Category
{
private String id;
private String name;
}
3.Experts array pojo:
public class Experts
{
private String id;
private String name;
private String title;
private String description;
private String profile;
}
Am using Retrift 2.
private RestManager mManager;
List<Expert> mExperts = new ArrayList<>();
....
Call<ExpertsObj> call = mManager.getExpertsService().listAllExperts();
call.enqueue(new Callback<ExpertsObj>() {
#Override
public void onResponse(Call<ExpertsObj> call, Response<ExpertsObj> response) {
if (response.isSuccess()) {
ExpertsObj expertsObj = response.body();
mExperts = expertsObj.getExperts();
....}
At a loss how to parse the profile-url name-value pair and display the results in a detail layout in android.
Any help is appreciated.
New in android. Please excuse if anything is not explained properly.

Related

Error parsing JSON (MismatchedInputException)

I'm having problems parsing JSON, this is the error:
out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<packagename....>` out of START_OBJECT token
And I know why it is happening I just don't know how to fix it. This JSON works:
{
"status_code": "SUCCESS",
"time": {
"date": "Mar 23, 2021 1:14:39 AM"
},
"info": [
{
"person": "2.2",
"role": "TEACHER"
},
{
"person": "2.3",
"role": "TEACHER"
}
]
}
This one does not:
{
"status_code": "SUCCESS",
"time": {
"date": "Mar 23, 2021 3:49:27 AM"
},
"info": {
"id": "1",
"person": [
{
"identifier": "John",
"role": "TEACHER"
},
{
"identifier": "Homer",
"role": "TEACHER"
},
{
"identifier": "Michael",
"role": "TEACHER"
},
{
"identifier": "Sarah",
"role": "TEACHER"
}
]
}
}
The problem seems to be the { character in front of the info field because with [ works. So this is the method I'm using to parse the JSON:
public Mono<PersonResponse> searchById(String id) {
return webClient.get().uri(id).retrieve().bodyToMono(PersonResponse.class);
}
Also tried:
public Mono<PersonResponse[]> searchById(String id) {
return webClient.get().uri(id).retrieve().bodyToMono(PersonResponse[].class);
}
Error right on line: 1, column: 1. Any suggestions of how to implement the method?
EDIT: Added classes.
PersonResponse:
public class PersonResponse implements Serializable{
private static final long serialVersionUID = 7506229887182440471L;
public String status_code;
public Timestamp time;
public List<PersonDetails> info;
public PersonResponse() {}
...getters / setters / toSting
PersonDetails:
public class PersonDetails implements Serializable{
private static final long serialVersionUID = 1294417456651475410L;
private int id;
private List<Person> person;
public PersonDetails(int version) {
super();
this.version = version;
}
...getters / setters / toSting
Person
public class Person implements Serializable{
private static final long serialVersionUID = 3290753964441709903L;
private String identifier;
private String role;
public Person(String identifier, String role) {
super();
this.identifier = identifier;
this.role = role;
}
...getters / setters / toSting
The problem isn't the JSON necessarily, it's that the JSON structure doesn't match your PersonResponse class. There's an info variable in PersonResponse that requires an array of what I assume to be persons, in the second example you're trying to push an object in there, which you can't. You have to either change your JSON, which you don't seem to want in this case, or the class you're trying to parse it to.
You need to restructure the info variable in PersonResponse to match the object you're trying to parse to it.

How can I convert a JSON string of objects into an ArrayList using Gson?

So I have a JSON string of countries like this:
{
"details": [
{
"country_id": "1",
"name": "Afghanistan",
"regions": null
},
{
"country_id": "2",
"name": "Albania",
"regions": null
},
{
"country_id": "3",
"name": "Algeria",
"regions": null
},
... and so on
}
Now I want to have a method that tries to convert this into an ArrayList of countries.
public static ArrayList<GFSCountry> get() {
return new Gson().fromJson(countriesJson, new TypeToken<ArrayList<GFSCountry>>(){}.getType());
}
But I get an
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path
As per request, here is my GFSCountry class:
#SerializedName("country_id")
#Expose
private String countryId;
#SerializedName("name")
#Expose
private String name;
#SerializedName("regions")
#Expose
private Object regions;
public String getCountryId() {
return countryId;
}
public void setCountryId(String countryId) {
this.countryId = countryId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getRegions() {
return regions;
}
public void setRegions(Object regions) {
this.regions = regions;
}
I know I should adjust something either from the JSON string or the method. Any help?
Since the list is nested in your JSON you will need a small mapping class that contains the list.
Try
static class GFSCountryList {
public List<GFSCountry> details;
}
public static List<GFSCountry> get() {
return new Gson().fromJson(countriesJson, GFSCountryList.class).details;
}
It seems to me that Gson is expecting your json to be like this
[
{
"country_id": "1",
"name": "Afghanistan",
"regions": null
},
{
"country_id": "2",
"name": "Albania",
"regions": null
},
{
"country_id": "3",
"name": "Algeria",
"regions": null
},
... and so on
]
But it encounters an object (marked by { })
Either you have the possibility to change your json format, or you create a class with a "details" attribut as a list to be compatible with the json's format.

Deserialize complex JSON to Java, classes nested multiple levels deep

I am trying to make the Json output from Cucumber into a single Java object. This contains objects nested four levels deep, and I am having trouble deserializing it. I am presently using Jackson, but open to suggestions.
Here is my Json code:
{
"line": 1,
"elements": [
{
"line": 3,
"name": "Converteren centimeters naar voeten/inches",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-centimeters-naar-voeten/inches",
"type": "scenario",
"keyword": "Scenario",
"steps": [
{
"result": {
"duration": 476796588,
"status": "passed"
},
"line": 4,
"name": "maak Maten-object aan met invoer in \"centimeters\"",
"match": {
"arguments": [
{
"val": "centimeters",
"offset": 37
}
],
"location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)"
},
"keyword": "Given "
},
{
"result": {
"duration": 36319,
"status": "passed"
},
"line": 5,
"name": "ik converteer",
"match": {
"location": "StepDefinition.converteerMaten()"
},
"keyword": "When "
},
{
"result": {
"duration": 49138,
"status": "passed"
},
"line": 6,
"name": "uitvoer bevat maat in \"voeten/inches\"",
"match": {
"arguments": [
{
"val": "voeten/inches",
"offset": 23
}
],
"location": "StepDefinition.uitvoerBevatMaatIn(String)"
},
"keyword": "Then "
}
]
},
{
"line": 8,
"name": "Converteren voeten/inches naar centimeters",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-voeten/inches-naar-centimeters",
"type": "scenario",
"keyword": "Scenario",
"steps": [
{
"result": {
"duration": 84175,
"status": "passed"
},
"line": 9,
"name": "maak Maten-object aan met invoer in \"voeten/inches\"",
"match": {
"arguments": [
{
"val": "voeten/inches",
"offset": 37
}
],
"location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)"
},
"keyword": "Given "
},
{
"result": {
"duration": 23928,
"status": "passed"
},
"line": 10,
"name": "ik converteer",
"match": {
"location": "StepDefinition.converteerMaten()"
},
"keyword": "When "
},
{
"result": {
"duration": 55547,
"status": "passed"
},
"line": 11,
"name": "uitvoer bevat maat in \"centimeters\"",
"match": {
"arguments": [
{
"val": "centimeters",
"offset": 23
}
],
"location": "StepDefinition.uitvoerBevatMaatIn(String)"
},
"keyword": "Then "
}
]
}
],
"name": "Applicatie neemt maten in cm en converteert ze naar voet/inch, en vice versa",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa",
"keyword": "Feature",
"uri": "sample.feature"
}
I have tried a number of different approaches. First I used nested inner classes, but it appeared you had to make them static, which I feared would not work since I have multiple instances of the same object within one (multiple "element"-objects in the root, for example). Then I tried putting them in separate classes, with Json annotations. Here's where that got me (omitting setters):
public class CucumberUitvoer {
private String name;
private String description;
private String id;
private String keyword;
private String uri;
private int line;
#JsonProperty("elements")
private List<FeatureObject> elements;
public CucumberUitvoer(){}
}
public class FeatureObject {
private String name;
private String description;
private String id;
private String type;
private String keyword;
private int line;
#JsonProperty("steps")
private List<StepObject> steps;
public FeatureObject() {
}
}
public class StepObject {
#JsonProperty("result")
private ResultObject result;
private String name;
private String given;
private String location;
private String keyword;
private int line;
#JsonProperty("match")
private MatchObject match;
public StepObject(){}
}
public class ResultObject {
private int duration;
private String status;
public ResultObject(){}
}
public class MatchObject {
#JsonProperty("arguments")
private List<ArgumentObject> arguments;
private String location;
public MatchObject(){}
}
public class ArgumentObject {
private String val;
private String offset;
public ArgumentObject(){}
}
For clarification, here's a class diagram of how the nesting works.
This solution gives me the following error:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of nl.icaprojecten.TestIntegratieQuintor.JSONInterpreter.CucumberUitvoer out of START_ARRAY token
Here is the code doing the actual mapping:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
CucumberUitvoer obj1 = null;
try {
obj1 = mapper.readValue(json, CucumberUitvoer.class);
} catch (IOException e) {
e.printStackTrace();
}
Is there a quick fix to this approach to make it work, or should I try something entirely different?
Ok I spent some time debugging and trying to figure out what was the problem, and finally was something pretty obvious.
implements Serializable
Thats the line I added to MatchObject and worked.
When we try to deserialize some object first we have to make those classes implements the interface Serializable
I just tried your sample code and oddly, it works.
Can you please double check your imports, if the JSON is coming in as provided and the getters, setters, constructors are actually there?
You can get the idea from this code to deserialize,
public class testCustomDeSerializer extends JsonDeserializer<test> {
public testCustomDeSerializer() {
this(null);
}
public TestCustomDeSerializer(Class t) {
// super(t);
}
#Override
public Test deserialize(JsonParser p, DeserializationContext ctx) throws IOException, JsonProcessingException {
ObjectCodec objectCodec = p.getCodec();
JsonNode node = objectCodec.readTree(p);
ObjectMapper objectMapper = new ObjectMapper();
Test test= new Test();
test.setId(node.get("line").asText());
List<elements> elementList = new ArrayList<>();
JsonNode elementsNode = node.get("elements");
Iterator<JsonNode> slaidsIterator = elementsNode.elements();
while (slaidsIterator.hasNext()) {
Steps steps= new Steps();
JsonNode slaidNode = slaidsIterator.next();
JsonNode stepNode= (JsonNode) slaidNode.get("Steps");
BoundingPoly in = objectMapper.readValue(stepNode.toString(), Steps.class);
elementsNode.setSteps(in);
/// continue
return
}
Hope it helps

Java class mapping for WordPress JSON - How to Get Categories / Tags

I am using JackSON Library to Parse Wordpress JSON to a Java Class. The JSON can be seen at the following link:
https://public-api.wordpress.com/rest/v1.1/sites/www.gjtutorial.com/posts?number=10&category=job-recruitment&pretty=1
I have been able to get the array of Posts with some of its nodes. However I can't understand how to get the list of Categories and Tags for each post.
My current Object Classes are:
public class WpJson {
public int found;
public List<Post> posts;
}
public class Post {
public int ID;
public String date;
public String modified;
public String title;
public String URL;
public String content;
public String excerpt;
}
This is how Tags and Categories are Structured in JSON:
"tags": {
"Medical Officers": {
"ID": 272,
"name": "Medical Officers",
"slug": "medical-officers",
"description": "",
"post_count": 11,
"meta": {
"links": {
"self": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:medical-officers",
"help": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:medical-officers\/help",
"site": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311"
}
}
},
"Officers": {
"ID": 415,
"name": "Officers",
"slug": "officers",
"description": "",
"post_count": 61,
"meta": {
"links": {
"self": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:officers",
"help": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:officers\/help",
"site": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311"
}
}
},
"Trainee Engineers": {
"ID": 600,
"name": "Trainee Engineers",
"slug": "trainee-engineers",
"description": "",
"post_count": 6,
"meta": {
"links": {
"self": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:trainee-engineers",
"help": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/tags\/slug:trainee-engineers\/help",
"site": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311"
}
}
}
},
"categories": {
"Jobs and Recruitment": {
"ID": 67,
"name": "Jobs and Recruitment",
"slug": "job-recruitment",
"description": "Employment, Recruitment, Job, Walk In, Interview, Entrance notification for Banks, Staff Selection Commission, SSC, Railway Recruitment Board, RRB, Public Service Commission, UPSC, Universities etc.",
"post_count": 1030,
"meta": {
"links": {
"self": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/categories\/slug:job-recruitment",
"help": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311\/categories\/slug:job-recruitment\/help",
"site": "https:\/\/public-api.wordpress.com\/rest\/v1.1\/sites\/63677311"
}
},
"parent": 0
}
}
I cant comment but looking at the Post class. I do not see categories or tags in it. For example can you get author ??
Here is a example.
http://tutorials.jenkov.com/java-json/jackson-objectmapper.html
Try below code
public class Post {
public int ID;
public String date;
public String modified;
public String title;
public String URL;
public String content;
public String excerpt;
public List<Tags> tags;
public List<Categories> categories;
}
public class Tag extends BasicField{}
public class Categorie extends BasicField{}
create BasicField class as fields are common between Tag and Categorie

JSON output displaying incorrectly when doing GET using Jersey REST

Im very new to Jersey REST and I'm trying to build a sample library system. I have created my BookResource.java and I want it to display the following output in browser:
{
“book” : {
“isbn” : 1,
“title” : “Programming Amazon EC2”,
“publication-date” : “2/11/2011”,
“language” : “eng”,
“num-pages”: 185,
“status” : “available”,
“authors” : [
{ “rel”: “view-author”, “href”: “/books/1/authors/1”, “method”: “GET” },
{ “rel”: “view-author”, “href”: “/books/1/authors/2”, “method”: “GET” }
]
},
"links" : []
}
My Book.java is below:
public class Book
{
private long isbn;
private String title;
#JsonProperty("publication-date")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy")
private String date;
private String language;
private String status;
#JsonProperty("num-pages")
private Integer num_pages;
#JsonProperty("authors")
private ArrayList<Author> authorList;
public Book() {}
//getters and setters
}
Author.java
public class Author
{
#JsonProperty("name")
private String name;
public Author() {}
public String getAuthor() {
return name;
}
public void setAuthor(String newAuthor){
this.name = newAuthor;
}
}
BookRepository.java
public class BookRepository implements BookRepositoryInterface {
public ArrayList<Author> getAuthorByIsbn(Long isbn)
{
Book newBook = bookInMemoryMap.get(isbn);
ArrayList<Author> authorList = newBook.getAuthor();
return authorList;
}
}
However my actual GET response on browser is showing as:
{
"book": {
"isbn": 1,
"title": "Programming EC2r",
"language": "eng",
"status": "available",
"author": [{
"name": "auth1",
"author": "auth1"
}, {
"name": "auth2",
"author": "auth2"
}],
"num_Pages": 185,
"publication-date": "2/11/2011",
"num-pages": 185,
"authors": [{
"name": "auth1",
"author": "auth1"
}, {
"name": "auth2",
"author": "auth2"
}]
}
BookResource.java
public class BookResource
{
#GET
#Path("/{isbn}")
#Timed(name = "view-book")
public BookDto getBookByIsbn(#PathParam("isbn") LongParam isbn)
{
Book book = bookRepository.getBookByISBN(isbn.get());
BookDto bookResponse = new BookDto(book);
// add more links
bookResponse.addLink(new LinkDto("view-book", "/books/" + book.getIsbn(),"GET"));
return bookResponse;
}
}
I am getting multiple values for author and num_pages and cannot seem to get the output displayed correctly.
I have tried #JsonPropertyOrder, but it didn't work.
Also, in debug I checked that the Book resource is getting stored and retrieved correctly. It's only the JSON output which is displaying multiple values. How can I correct that?
Also, how can I display the links for "authors" as required ?
Thanks to #SvetlinZarev, I was able to solve the issue of multiple values being displayed by putting the #JsonProperty only on the getter methods.
#JsonProperty("name")
public String getAuthor() {
return name;
}
It worked perfectly fine and it's displaying my correct output as below:
{
"book": {
"isbn": 1,
"title": "Programming EC2r",
"publication-date": "2/11/2011",
"language": "eng",
"num-pages": 185,
"status": "available",
"authors": [{
"name": "auth1"
}, {
"name": "auth2"
}]
},
"links": []
}
Thanks again to everyone for your prompt responses to a newbie like me! :)

Categories