Deserialization fails when there is no default constructor - java

I 'm trying to use Fastjson library for JSON serialization.
When I try to deserialize , it fails showing no default constructor error.
Note: My class here is a toy example. I realty, it contains so many references to other classes which are in other maven projects and its practically not possible to modify every class.
Here is the code.
Student s = new Student("vineel", "20");
String hell = JSON.toJSONString(s);
Student model2 = JSON.parseObject(hell, Student.class);
System.out.println(model2);
public class Student {
private String name;
private String age;
Student(String name,String age){
this.name = name;
this.age = age;
}
#override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
Here is the error:
Exception in thread "main" com.alibaba.fastjson.JSONException: default constructor not found. class com.alibaba.fastjson.Student
at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:467)
at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:213)
at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(ParserConfig.java:656)
at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:573)
at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:386)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:658)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:365)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:269)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:488)
at com.alibaba.fastjson.JSON.main(JSON.java:1068)

Change constructor to.
#JsonCreator
public Student(#JsonProperty("name") String name, #JsonProperty("age") String age){
this.name = name;
this.age = age;
}

So create a TO class.
Student model2 = JSON.parseObject(hell, StudentTO.class).asStudent();
System.out.println(model2);
public class StudentTO {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Student asStudent() {
return new Student(name, age);
}
}

Related

How to extract field value from another field that is of type Object

I'm new to java reflexion and I'm trying to integrate SQLite with java.
I have 2 objects Person and Department. There is relation OneToMany between them.
As I'm working on save functionality (SQLite) I want to extract field names and its values so I can build full query. I have no problem with extracting names and values of fields that are of primitive type (String, int etc.). I have problem with type of Object (in this case it is Department field in Person object).
I'm able to print object but unable to access its fields (namely pk).
Could you help me please?
METHOD FOR EXTRACTING FIELDS
// method for extracting fields
private StringBuilder getFieldsWithValues(Object entity) throws IllegalAccessException, NoSuchFieldException {
StringBuilder query = new StringBuilder();
for (Field field : entity.getClass().getDeclaredFields()) {
System.out.print((field.getName() + " - "));
field.setAccessible(true);
// TODO: eliminate if statement from for cycle
if (field.isAnnotationPresent(ManyToOne.class)) {
// HERE I want to extract the pk value from Department object
System.out.println(field.get(entity));
} else {
System.out.println(field.get(entity));
}
}
return query;
}
DEPARTMENT OBJECT
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Department {
#Id
private long pk;
private String name;
private String code;
public Department() {
}
public Department(String name, String code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String toString() {
return String.format("Department %d: %s (%s)", pk, name, code);
}
}
PERSON OBJECT
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
public class Person {
#Id
private long id;
private String surname;
private String name;
private int age;
#ManyToOne
private Department department;
public Person(String surname, String name, int age) {
this.surname = surname;
this.name = name;
this.age = age;
}
public Person() {
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public long getId() {
return id;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
#Override
public String toString() {
return String.format("Person %d: %s %s (%d)", id, surname, name, age);
}
}

Given the above Java code fragment, SELECT the statement which identifies the number of APIs available to demonstrate dynamic polymorphism

public class Person {
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Person {
private double gpa;
public Student(String name, double gpa) {
super(name);
this.gpa = gpa;
}
public double getGpa() {
return gpa;
}
public void setGpa(double gpa) {
this.gpa = gpa;
}
#Override
public String toString() {
return "Student " + getName() + ", with a GPA of " + gpa;
}
}
Given the above Java code fragment, SELECT the statement which identifies the number of APIs available to demonstrate dynamic polymorphism.

Getting average data from list using Collectors.averagingInt java

I have a code with two different methods, but one of them is working and other is not compilled, I don`t get what is wrong.
Here is the code:
public class CollectorOperations {
public int averageAgeInt(List<Person> persons) {
return persons.stream()
.collect(Collectors.averagingInt(person -> person.getAge()));
}
public double averageAgeDouble(List<Person> personList, int i) {
return personList.stream()
.collect(Collectors.averagingInt(person -> person.getAge()));
}
}
class Person {
private String name;
private String lastName;
private int age;
public Person(String name, String lastName) {
this.name = name;
this.lastName = lastName;
}
public Person(String name, String lastName, int age) {
this.name = name;
this.lastName = lastName;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
The only difference between this two methods is return type, when return type is int I can't get person.age() from lambda expression, but when I change return type to double it's working.
P.S.
sorry for my english.
It is not compiling due a type mismatch here:
persons.stream().collect(Collectors.averagingInt(person -> person.getAge()));
That operation returns an object of the type Double, but your method is defined to return an integer.
The reason is that a Double object can not be cast into an int, but since that is a Double object, you can get the integer value calling the method Double#intValue()
You need to do something like
return persons.stream().collect(Collectors.averagingInt(person -> person.getAge())).intValue();
I don’t get why you have a parameter int i in the method averageAgeDouble (the variable is never used), so you can define a more elegant way if you get rid off that variable:
public int averageAgeInt(List<Person> persons) {
return (int) averageAgeDouble(persons);
}
public double averageAgeDouble(List<Person> personList) {
return personList.stream().collect(Collectors.averagingInt(person -> person.getAge()));
}

Java remove User defined object from Tree Set

I have created a class of Patient object containing patient name and gender and I want to remove it base on Patient name. What is the correct way to do it?
This is my Patient object:
class Patient {
private String name;
private int gender;
public Patient(String name, int gender){
this.name = name;
this.gender = gender;
}
public String getName(){
return this.name;
}
public int getGender(){
return this.gender;
}
public void setName(String name){
this.name = name;
}
public void setGender(int gender){
this.gender = gender;
}
}
This is my Treeset declaration: private TreeSet<Patient> ts = new TreeSet<Patient>(new nameComp());
This is my remove method (I don't know how to start)
void RemovePatient(String patientName) {
}
Just iterating and removing while doing so, will result in a Concurrent Modification Exception. You could temp save the item to remove and remove it later:
For example:
void removePatient(String patientName) {
Person deleteThat;
for (Patient p : ts){
if(p.getName().equals(patientName){
deleteThat = p;
}
}
if(deleteThat != null){
ts.remove(deleteThat);
}
}

Deserialize yaml to list of objects

Say I have a Yaml file like this,
people:
- name : Joe
surname : Barber
age : 16
- name : Andy
surname : Lots
age : 17
And I have a class like this,
public class people {
private String name;
private String surname;
private String age;
<!-- With getters and setters -->
}
How would i go about getting a list of people objects from the Yaml file?
Just getting the value from a key in the file is fairly simple but mapping it to a collection of objects is not.
I am using the snakeYaml lib.
i hope this can help you.
public class StackOverflow {
public static void main(String[] args) {
final URL resource = StackOverflow.class.getResource("people.yaml");
final Constructor peopleContructor = new Constructor(Group.class);
final TypeDescription peopleDescription = new TypeDescription(People.class);
peopleDescription.putMapPropertyType("people", People.class, Object.class);
peopleContructor.addTypeDescription(peopleDescription);
final Yaml yaml = new Yaml(peopleContructor);
try {
final Group group = (Group) yaml.load(resource.openStream());
for (final People people : group.getPeople()) {
System.out.println(people);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static class People {
private String name;
private String surname;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
return "People: {name: " + this.name + ", surname: " + this.surname + ", age: " + this.age + "}";
}
}
public static class Group {
private List<People> people;
public List<People> getPeople() {
return people;
}
public void setPeople(List<People> people) {
this.people = people;
}
}}

Categories