How to identify the missing type id in Jackson error?
UPDATE:
BusinessContact
class should be annotated with @JsonTypeName("business")
and PersonContact
class with @JsonTypeName("personal")
instead of @JsonTypeName("type")
because you shoud define specific type in inheritors.
@JsonTypeInfo
annotation can be removed from subclasses at all.
UPDATE 2:
Additionaly PersonContact
class should have default constructor:
public PersonContact(){}
An input JSON file is not a list it is an entity with two attributes allContacts
and size
. Thus it can't be mapped to ArrayList<BaseContact>
. So a new entity with these two attributes should be created:
public class ContactsWrapper
{
private List<BaseContact> allContacts;
private int size;
public List<BaseContact> getAllContacts()
{
return allContacts;
}
public void setAllContacts(List<BaseContact> allContacts)
{
this.allContacts = allContacts;
}
public int getSize()
{
return size;
}
public void setSize(int size)
{
this.size = size;
}
}
Code that reads JSON should be changed:
ContactsWrapper contactsWrapper = new ObjectMapper().readerFor(ContactsWrapper.class).readValue(new File(fn));
abl = contactsWrapper.getAllContacts();
Now JSON is mapped to ContactsWrapper
and list of contacts is assigned to abl
variable using getter.
james
Updated on July 13, 2022Comments
-
james almost 2 years
I am using Jackson to write JSON to a text file, the JSON represents 2 classes inherited from an abstract class but the error also occurs irrespective of whether both or either/or classes are used. The JSON appears to be written correctly but on reading, I get the following error:
Missing type id when trying to resolve subtype of [simple type, class model.BaseContact]: missing type id property 'type' at [Source: (File); line: 52, column: 1] json as follows: { "allContacts" : [ { "type" : "personal", "addressCity" : "Hamilton", "addressNum" : "199", "addressPOBox" : null, "addressPostCode" : null, "addressStreet" : "River Rd", "addressSuburb" : null, "email" : null, "latitude" : null, "longitude" : null, "name" : "silly simon", "notes" : null, "phoneNumber" : "09754321", "photoBytes" : null, "photoURL" : null }, { "type" : "personal", "addressCity" : "Auckland", "addressNum" : "482", "addressPOBox" : null, "addressPostCode" : null, "addressStreet" : "Smith Rd", "addressSuburb" : null, "email" : null, "latitude" : null, "longitude" : null, "name" : "paul smith", "notes" : null, "phoneNumber" : "0544555", "photoBytes" : null, "photoURL" : null }, { "type" : "personal", "addressCity" : "Appleby", "addressNum" : "123", "addressPOBox" : null, "addressPostCode" : null, "addressStreet" : "Apple rd", "addressSuburb" : null, "email" : null, "latitude" : null, "name" : "Steve Jobbs", "notes" : null, "phoneNumber" : "08004343", "photoBytes" : null, "photoURL" : null } ], "size" : 3 }
The error message refers to line 52 column 1, assuming the debugger starts at line 1 that would be the line after the final curly brace.
The
BaseContact
class header is as follows:import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonTypeInfo( use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(value=PersonContact.class, name= "personal"), @JsonSubTypes.Type(value= BusinessContact.class, name="business") }) public abstract class BaseContact { public String name; public String addressNum; public String addressStreet; public String addressSuburb; public String addressCity; public String addressPOBox; public String addressPostCode; public Double latitude; public Double longitude; public String photoURL; public String photoBytes; public String phoneNumber; public String email; public String notes; public BaseContact() { //DEFAULT CONSTRUCTOR } public BaseContact( String name, String addressNum, String addressStreet, String addressCity, String phoneNumber) { this.name = name; this.addressNum = addressNum; this.addressStreet = addressStreet; this.addressCity = addressCity; this.phoneNumber = phoneNumber; }
The calling function is as follows:
public BusinessService readAllData(String fn) { ArrayList<BaseContact> abl = new ArrayList<BaseContact>(); try { abl = new ObjectMapper().readerFor(BaseContact.class).readValue(new File(fn)); Log.d("qq","abl"+ abl); } catch (IOException e) { Log.d("qq", "failed reading " + e.getMessage().toString()); e.printStackTrace(); } BusinessService b = new BusinessService(); return b; }
The
BusinessContact
class ( inherits from abstractBaseContact
) is as follows:package model; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonTypeInfo( use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonTypeName("type") public class BusinessContact extends BaseContact { public String companyName; public String websiteURL; public String businessHours; //def constructor public BusinessContact(){ }; public BusinessContact(String name, String addressNum, String addressStreet, String addressCity, String phoneNumber, String companyName, String websiteURL, String businessHours) { super(name, addressNum, addressStreet, addressCity, phoneNumber); this.companyName = companyName; this.websiteURL = websiteURL; this.businessHours = businessHours; } //Getters and setters public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public String getWebsiteURL() { return websiteURL; } public void setWebsiteURL(String websiteURL) { this.websiteURL = websiteURL; } public String getBusinessHours() { return businessHours; } public void setBusinessHours(String businessHours) { this.businessHours = businessHours; } public String visitWebsite(int i ){ //get website, construct intent return"url intent"; } public Boolean isOpen(int i ){ //do math for day and time and return true if open return true; } @Override public String toString() { String output= this.getClass() + "name: "+ this.name + " " + "company"+ this.companyName + "Hours "+ this.businessHours + "Website "+ this.websiteURL+ " address: " + this.addressNum+ " , " + this.addressStreet + " , " + this.addressSuburb+ "," + this.addressCity +" , CODE " + this.addressPostCode + " PO BOX " + this.addressPOBox + "PH: " + this.phoneNumber + "email: " + this.email + "notes: "+ this.notes ; return output ; }
}
The
PersonContact
class ( inherits from abstractBaseContact
):package model; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonTypeName("type") public class PersonContact extends BaseContact { //constructor public PersonContact(String name, String addressNum, String addressStreet, String addressCity, String phoneNumber) { super(name, addressNum, addressStreet, addressCity, phoneNumber); } @Override public String toString() { String output = this.getClass() + "name: " + this.name + " " + " address: " + this.addressNum + " , " + this.addressStreet + " , " + this.addressSuburb + "," + this.addressCity + " , CODE /n " + this.addressPostCode + " PO BOX " + this.addressPOBox + "PH: " + this.phoneNumber + "email: " + this.email + "notes: " + this.notes; return output; } }
-
james over 4 yearsThanks , I have made those changes yet I still get "failed reading Missing type id when trying to resolve subtype of [simple type, class model.BaseContact]: missing type id property 'type' "
-
Ihor Patsian over 4 yearsI've updated the answer with additional steps that fix your problem. Please see UPDATE 2 section.
-
james over 4 yearsI cant upvote your answer but UPDATE2 is effective, many thanks Igor
-
vphilipnyc over 3 yearsThe NoArg constructor part was helpful here