I am trying to deserialize some JSON which I got from the eBay API but I am getting the error: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
The JSON that is returned has many levels to it. e.g.
{"searchResult":[{"#count":"100","item":[{"itemId":["281492499859"],"title":["Panasonic Lumix TZ20 Digital Camera in Good Condition"],... etc
This is for a property called itemId in CompletedListing (class defined below)
I am calling this method with the line:
CompletedListingContainer listing = mapper.readValue(new File("C:\\resource\\jsonresult.txt"), CompletedListingContainer.class);`
Here are my classes.
CompletedListingContainer
public class CompletedListingContainer {
private ArrayList<CompletedListing> item;
private ArrayList<SearchResult> searchResult;
private List<String> paginationOutput;
#JsonIgnore
public List<String> getPaginationOutput() {
return paginationOutput;
}
public ArrayList<SearchResult> getSearchResult() {
return searchResult;
}
public ArrayList<CompletedListing> getItem() {
return item;
}
}
SearchResult
public class SearchResult {
#JsonProperty("#count")
private String count;
private ArrayList<CompletedListing> item;
#JsonIgnore
public String getCount() {
return count;
}
public ArrayList<CompletedListing> getItem() {
return item;
}
}
CompletedListing
public class CompletedListing {
#JsonProperty("itemId")
private String itemId;
private String title;
#JsonProperty("itemId")
public String getItemId() {
return itemId;
}
#JsonProperty("title")
public String getTitle() {
return title;
}
}
Any help would be greatly appreciated. Let me know if you need any more information.
{"itemId":["281492499859"] means your CompletedListing.itemId property should be a list or array.
put private ArrayList<CompletedListing> item in your SearchResult class and remove it from CompletedListingContainer
look at your json file structure:
{
"searchResult":[
{
"count":"100",
"item":[
{"itemId":["281492499859"]...
},
....
}
try this online tool to generate Java classes from json
Related
I am struggling to deserialise complex nested Json data into Java objects I think my class structure is wrong. Here is my Json data:
{
"resultsPerPage": 20,
"startIndex": 0,
"totalResults": 2,
"result": {
"dataType": "CPE",
"feedVersion": "1.0",
"cpeCount": 2,
"feedTimestamp": "2021-03-19T13:06",
"cpes": [
{
"deprecated": false,
"cpe23Uri": "cpe:2.3:o:microsoft:windows_10:1511:*:*:*:*:*:x64:*",
"lastModifiedDate": "2015-12-09T17:28Z",
"titles": [
{
"title": "Microsoft Windows 10 1511 64-bit",
"lang": "en_US"
}
],
"refs": [
{
"ref": "https://www.microsoft.com/en-us/",
"type": "Vendor"
}
],
"deprecatedBy": [],
"vulnerabilities": [
"CVE-2016-0174",
"CVE-2016-0171"
]
}
Here is the class I map the Json data to:
public class RESPONSE {
Result result;
}
class Result {
List<Cpes> cpes;
}
class Cpes {
String cpe23Uri;
List<Titles> titles;
List<String> vulnerabilities;
}
class Titles{
String title;
}
When I debug my code r in the below code is null and I think it's because my RESPONSE class isn't set up right.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
RESPONSE r = mapper.readValue(response.getContent(), RESPONSE.class);
System.out.println(r);
Your object model should match the structure of the JSON you are trying to read. For example, it'll have to look something like the following:
public class Response {
private int resultsPerPage;
private int startIndex;
private int totalResults;
private Result result;
// Should include getters and setters
}
public class Result {
private String dataType;
private String feedVersion;
private int cpeCount;
private String feedTimestamp;
private CPE[] cpes;
// Should include getters and setters
}
public class CPE {
private boolean deprecated;
private String cpe23Uri;
private String lastModifiedDate;
private Title[] titles;
private Ref[] refs;
private String[] deprecatedBy;
private String[] vulnerabilities;
// Should include getters and setters
}
public class Title {
private String title;
private String lang;
// Should include getters and setters
}
public class Ref {
private String ref;
private String type;
// Should include getters and setters
}
Note that to keep the code sample short, I've omitted the getters and setters.
Edit: As Tugrul pointed out below, since fail on unknown property is disabled, it won't fail if there are missing fields in your model. The only issue is the missing getters and setters.
I also found another way to solve this issue for future reference.
I used a tree data structure to access my Json fields which means I can just declare a flat class:
public class Test {
private String cpe23Uri;
private String title;
private List<String> vulnerabilities;
public String getCpe23Uri() {
return cpe23Uri;
}
public void setCpe23Uri(String cpe23Uri) {
this.cpe23Uri = cpe23Uri;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getVulnerabilities() {
return vulnerabilities;
}
public void setVulnerabilities(List<String> vulnerabilities) {
this.vulnerabilities = vulnerabilities;
}
}
I then mapped using a Tree
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonNode resultNode = mapper.readTree(response.getContent());
Test t = new Test();
t.setCpe23Uri(resultNode.get("result").get("cpes").get(0).get("cpe23Uri").textValue());
I have a json context like below:
{
"data": {
"details": {
"en-CA": {
"languageCode": "en-CA",
"isPrimaryLocale": false
},
"en-US": {
"languageCode": "en-US",
"isPrimaryLocale": true,
"languageDisplayName": "English (United States)",
}
}
}
}
To map it with GSON in java:
I created this classes:
public class ApiResponseSingleDto
{
private ResponseDetail data;
}
public class ResponseDetail
{
private ResponseDetails details;
#Getter
public static class ResponseDetails
{
public HashMap<String, LocaleDetail> row = new HashMap<>();
}
}
public class LocaleDetail
{
private String languageCode;
private Boolean isPrimaryLocale;
private String languageDisplayName;
}
When I try to map json to Java POJO class, HashMap doesn't work. Is there any suggestion?
To map it:
GSON.fromJson("...json", Type type...);
Just try to replace:
public class ApiResponseSingleDto
{
private ResponseDetail data;
}
public class ResponseDetail
{
private Map<String, LocaleDetail> details;
}
public class LocaleDetail
{
private String languageCode;
private Boolean isPrimaryLocale;
private String languageDisplayName;
}
Also json seems to be incorrect: "languageDisplayName": "English (United States)",
should be just "languageDisplayName": "English (United States)"
One more note: I believe you should have public fields or at least getters for them
Hi I am new ElasticSearch, I am using spring data. I have 2 API which saves data in article and discourse model using elastic search, now when a client app makes a API call for both article and discourse search it gives all article first and then discourse data. but i want to randomize the response how can i do that?
my article model class as follows
#AllArgsConstructor
#Data
#Document(indexName="articles", createIndex=true)
public class Article implements ITResult {
private String id;
private String hostContentId;
private String title;
private List<String> categories;
private String searchResultId;
#Override
public String getSummary() {
return excerpt;
}
#Override
public ContentType getContentType() {
return ContentType.ARTICLE;
}
#Override
public String getHostContentId() {
return hostContentId;
}
#Override
public String getUrl() {
return link;
}
#Override
public String getSearchResultId() {
return searchResultId;
}
public void setSearchResultId(String searchResultId) {
this.searchResultId = searchResultId;
}
}
I have done the following
SearchQuery query = new NativeSearchQueryBuilder().withIndices("articles","course")
.withPageable(new PageRequest(offset,limit))
.withFilter(multiMatchQuery(string, new String[] { "title", "excerpt", "author_name", "link"}))
.build();
I am facing an issue while converting an JSON to a Java Object.
My Json is as below
{
"_id":{
"$oid":"5981428cf1aa82a313540b76"
},
"productId":1,
"name":"The Big Lebowski",
"currency":{
"currency":"USD",
"value":40.5
}
}
I am retrieving json as DBObject for Product from the MongoDB database.
DBObject dbObject = productsCollection.findOne(searchQuery);
if(dbObject != null)
{
Product product = (Product) AppUtils.fromDBObject(dbObject, Product.class);
return Optional.of(product);
}
Product is return as
Product[productId = 1, productName= null, currencyPrice = null]
My fromDBObject method in AppUtils.java is as below :
public static Object fromDBObject(DBObject dbObj, Class<?> clazz)
{
String json = dbObj.toString();
return new Gson().fromJson(json, clazz);
}
My POJO is as below :
public class Product
{
private long productId;
private String productName;
private CurrencyPrice currencyPrice;
// getter and setter
}
public class CurrencyPrice
{
private double value;
private String currency;
// getter and setter
}
I am unable to understand where it is going wroing for the DBObject object with json to translate to Product object.
Thanks !
try changing your POJO property names to match
public class Product
{
private long productId;
private String name;
private CurrencyPrice currency;
// getter and setter
}
I am making rest web-services my code is:
#Path("/add")
#POST
#Produces(MediaType.APPLICATION_JSON)
public Response addMembers(List<GroupMemberMap> groupMemberMaps){
String message = "";
System.out.println("Inside addMembers of class "+this.toString());
try {
DBConnection.insertMembers(groupMemberMaps);
message = "Member(s) added";
return Response.status(Status.CREATED)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.build();
} catch(SQLException sqle){
System.out.println("addMembers catch sqle");
message = "A problem occured while adding members : "+sqle.getMessage();
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.build();
}
catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("Inside addMembers catch "+e.getMessage());
message = "A problem occured while adding members : "+e.getMessage();
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.build();
}
}
but when i call it with this Json :
[
{
"userId":"3",
"groupId":"4"
}
]
I'm getting following Exception:
javax.servlet.ServletException: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "userId" (Class com.tazligen.model.GroupMemberMap), not marked as ignorable at [Source: org.apache.catalina.connector.CoyoteInputStream#14ec141; line: 2, column: 15] (through reference chain: com.tazligen.model.GroupMemberMap["userId"])
My GrouMemberMap model class is :
package com.tazligen.model;
#XmlRootElement
public class GroupMemberMap {
private String userId;
private String groupId;
public String getUserid() {
return userId;
}
public void setUserid(String userId) {
this.userId = userId;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
} }
I have tried another method just like this :
#Path("/membertest")
#POST
public String test(List<User> members){
return "Test subresource members working";
}
with json
[{
"userId":"3",
"userName":"John"}]
but this works alright :/
Need Someone help.
I can make following observations after looking at GroupMemberMap Class:
Constructor is missing.
Getter-Setter for the UserId is incorrect.
Also, you can add optional #JsonIgnoreProperties to ignore all other unknown fields.
Here is the corrected code snippet:
package com.tazligen.model;
#XmlRootElement
#JsonIgnoreProperties(ignoreUnknown = true)
public class GroupMemberMap {
#JsonProperty("userId")
private String userId;
#JsonProperty("groupId")
private String groupId;
/* Add Constructor */
public GroupMemberMap() {}
/* Corrected Name */
public String getUserId() {
return userId;
}
/* Corrected Name */
public void setUserId(String userId) {
this.userId = userId;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
}
I was using lombok to generate getters and setters with #Getter and #Setter annotation. Now what solved a similar issue for me was converting data type of a field from primary java type boolean to Boolean. Lombok only generated a getter for it only if I used Boolean fieldName.
Just modify userId and groupId public. By default, Jackson works on public member variables.
I think JsonIgnoreProperties is not solution as it is used to ignore whatever it doesn't recognize.
public String userId;
public String groupId;
above solution worked for me and I had string array inside json object .
I used JsonIgnore properties and replaced square brackets for the objects inside json object..