Error parsing JSON (MismatchedInputException) - java

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.

Related

Deserializing complex json with matching objects by id (Jackson)

I have a proprietary API that return a complex JSON like:
{
"store": "store_name",
"address": "store_address",
"department": [
{
"name": "d1",
"type": "t1",
"items": [
"i1",
"i2"
]
},
{
"name": "d2",
"type": "t2",
"items": [
"i3"
]
}
],
"itemDescriptions": [
{
"id": "i1",
"description": "desc1"
},
{
"id": "i2",
"description": "desc2",
"innerItems": [
"i2"
]
},
{
"id": "i3",
"description": "desc3"
}
]
}
Is it possible to deserialize this JSON using Jackson into:
#AllArgsConstructor
class Store {
private final String store;
private final String address;
private final List<Department> departments;
/*some logic*/
}
#AllArgsConstructor
class Department {
private final String name;
private final String type;
private final List<Item> items;
/*some logic*/
}
#AllArgsConstructor
class Item {
private final String id;
private final String description;
private final List<Item> innerItems;
/*some logic*/
}
I tried to find answers, but find only this question without solution.
I know that I can do it in my code (deserialize as it is and create objects from result), but its very memory intensive (I have a lot of json and it can be large).
I know that I can write fully custom deserializer, but in this case, I have to describe the deserialization of each field myself - in case of some changes, I will have to change the deserializer, and not just the class(POJO/DTO).
Is there a way to do this with Jackson (or Gson) or with a minimal (preferably relatively generic) amount of my code?

How to write complex string into Gson classes

I've been racking my brain attempting to make pojos to consume the following json string. One thing I've been doing is making multiple pojos within pojos similar to what would be necessary inside of spring boot. Not sure if this is also needed for GSON. After numerous attempts I've still havent gotten it. Thanks for any advice in advance.
Json String:
"results": [
{
"id": "superficial",
"language": "en",
"lexicalEntries": [
{
"derivatives": [
{
"id": "superficialness",
"text": "superficialness"
}
],
"entries": [
{
"etymologies": [
"late Middle English: from late Latin superficialis, from Latin superficies (see superficies)"
],
"grammaticalFeatures": [
{
"text": "Positive",
"type": "Degree"
}
],
"homographNumber": "000",
"senses": [
{
"definitions": [
"existing or occurring at or on the surface"
],
"examples": [
{
"text": "the building suffered only superficial damage"
}
],
"id": "m_en_gbus1014360.017",
"short_definitions": [
"existing or occurring at or on surface"
],
"subsenses": [
{
"definitions": [
"situated or occurring on the skin or immediately beneath it"
],
"domains": [
"Anatomy",
"Medicine"
],
"examples": [
{
"text": "the superficial muscle groups"
}
],
"id": "m_en_gbus1014360.019",
"short_definitions": [
"situated or occurring on skin or immediately beneath it"
]
},
{
"definitions": [
"appearing to be true or real only until examined more closely"
],
"examples": [
{
"text": "the resemblance between the breeds is superficial"
}
],
"id": "m_en_gbus1014360.020",
"short_definitions": [
"appearing to be true or real only until examined more closely"
],
"thesaurusLinks": [
{
"entry_id": "superficial",
"sense_id": "t_en_gb0014419.004"
}
]
},
{
"definitions": [
"not thorough, deep, or complete; cursory"
],
"examples": [
{
"text": "he had only the most superficial knowledge of foreign countries"
}
],
"id": "m_en_gbus1014360.021",
"short_definitions": [
"not thorough or complete"
],
"thesaurusLinks": [
{
"entry_id": "superficial",
"sense_id": "t_en_gb0014419.003"
}
]
},
{
"definitions": [
"not having or showing any depth of character or understanding"
],
"examples": [
{
"text": "perhaps I was a superficial person"
}
],
"id": "m_en_gbus1014360.022",
"short_definitions": [
"not having or showing any depth of character or understanding"
],
"thesaurusLinks": [
{
"entry_id": "superficial",
"sense_id": "t_en_gb0014419.006"
},
{
"entry_id": "superficial",
"sense_id": "t_en_gb0014419.002"
}
]
}
],
"thesaurusLinks": [
{
"entry_id": "superficial",
"sense_id": "t_en_gb0014419.001"
}
]
}
]
}
],
"language": "en",
"lexicalCategory": "Adjective",
"pronunciations": [
{
"dialects": [
"American English"
],
"phoneticNotation": "respell",
"phoneticSpelling": "ˌso͞opərˈfiSHəl"
},
{
"audioFile": "http://audio.oxforddictionaries.com/en/mp3/superficial_us_1.mp3",
"dialects": [
"American English"
],
"phoneticNotation": "IPA",
"phoneticSpelling": "ˌsupərˈfɪʃəl"
}
],
"text": "superficial"
}
],
"type": "headword",
"word": "superficial"
}
Pojos:
class Results {
private String id;
private String language;
private String lexicalEntries;
private String type;
private String word;
//
}
class Derivatives {
private String id;
private String text;
//
}
class Entries {
private String etymologies;
private String grammaticalFeatures;
private int homographNumber;
private List<String> senses;
//
}
public class LexicalEntries {
private Derivatives derivatives;
private List<Entries> entries;
private String language;
private String lexicalCategory;
private List<Pronunciations> pronunciations;
private String text;
//
}
public class Pronunciations {
private String dialects;
private String phoneticNotation;
private String phoneticSpelling;
//
}
class Senses {
private String definitions;
private String examples;
private String id;
private ShortDefinitions short_definitions;
private List<Subsenses> subsenses;
private List<ThesaurusLinks> thesaurusLinks;
//
}
class ShortDefinitions {
private String short_definitions;
//
}
class Subsenses {
private String definitions;
private String domains;
private String examples;
private String id;
private String shortDefinitions;
private String thesaurusLinks;
//
}
class ThesaurusLinks {
private String entry_id;
private String sense_id;
//
}
I have corrected your POJO class definitions as per your JSON.
I would recommend you reading JSON notation, how different data types are represented in it like Array/List, Object, String, int, boolean. It will clarify your understanding and you will know why your classes were not properly mapped to JSON data schema.
class Results {
private String id;
private String language;
private List<LexicalEntry> lexicalEntries;
private String type;
private String word;
//
}
public class LexicalEntry {
private List<Derivative> derivatives;
private List<Entry> entries;
private String language;
private String lexicalCategory;
private List<Pronunciation> pronunciations;
private String text;
//
}
class Derivative {
private String id;
private String text;
//
}
class Entry {
private List<String> etymologies;
private List<GrammaticalFeature> grammaticalFeatures;
private String homographNumber; //if it has quotes in JSON, it will be a string not int..JSON is a strongly typed object notation
private List<Sense> senses;
//
}
class GrammaticalFeature{
String text;
String type;
}
public class Pronunciation {
private String audioFile;
private List<String> dialects;
private String phoneticNotation;
private String phoneticSpelling;
//
}
class Sense {
private List<String> definitions;
private List<Example> examples;
private String id;
private List<String> short_definitions;
private List<Subsense> subsenses;
private List<ThesaurusLinks> thesaurusLinks;
//
}
class Example{
String text;
}
class Subsense {
private List<String> definitions;
private List<String> domains;
private List<Example> examples;
private String id;
private List<String> shortDefinitions;
private List<ThesaurusLink> thesaurusLinks;
//
}
class ThesaurusLink {
private String entry_id;
private String sense_id;
//
}

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

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.

serialize json to pojo class

I have a JSON response coming as shown below. I am trying to make a POJO for this so that I can serialize this JSON into my POJO.
{
"holder": [
{
"ids": [
{
"data": "abcdef1234",
"time": 1452720139465,
"days": 16813
},
{
"data": "abcdef12345678",
"time": 1452720139465,
"days": 16813
},
{
"data": "abcdef12345678901234",
"time": 1452720139465,
"days": 16813
}
],
"type": "HELLO"
}
]
}
And this is my POJO I was able to come up with but it doesn't look right.
public class TestResponse {
private List<Ids> holder;
private String type;
// getters and setters
public static class Ids {
private String data;
private long time;
private long days;
// getters and setters
}
}
My json is not getting serialized to my above POJO
go to this link www.jsonschema2pojo.org and past yout json and extract jar files and import in your project and do some changes link this.
$class TestResponse {
to
class TestResponse implement serializable{

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