I am trying to use google gson TypeAdapter for converting nested JSON into nested Java object having implementation of TypeAdapter for each class. But I don't want to write complete read() method logic in single adapter class. I have referred few questions and blog examples over net. But complete read logic is in single class.
For small nested object its fine to have logic in single Adapter but for big object (having more than 10-15 fields in each class) it's not good.
[Update]
For example json keys look same as of class attributes, but in actual I will be getting input as hyphen-separated-small-case
keys instead of Camel case
keys. So my json and java classes attribute names will not be same hence I have to write my custom logic for mapping.
Eg Sample Json input :
{
"id": 1,
"name": "Alex",
"emailId": "alex@gmail.com",
"address": {
"address": "21ST & FAIRVIEW AVE",
"district": "district",
"city": "EATON",
"region": "PA",
"postalCode": "18044",
"country": "US"
}
}
And Java beans are as below :
//Employee object class
public class Employee {
private int id;
private String name;
private String emailId;
private Address address;
..
}
//Address object class
public class Address {
private String address;
private String district;
private String city;
private String region;
private String postalCode;
private String country;
..
}
I want to have two different adapters and integrate multiple adapters in read() method.
public class EmployeeAdapter extends TypeAdapter<Employee> {
@Override
public void write(JsonWriter out, Employee employee) throws IOException {
//
}
@Override
public Employee read(JsonReader jsonReader) throws IOException {
//read logic for employee class using AddressAdapter for address json
}
}
public class AddressAdapter extends TypeAdapter<Address> {
@Override
public void write(JsonWriter out, Address address) throws IOException {
//
}
@Override
public Address read(JsonReader jsonReader) throws IOException {
//read logic for Address class
}
}
How can I use AddressAdapter inside EmployeeAdapter?
I had the same issue and found a suitable solution for me.
You can get a new TypeAdapter<T>
instance with help of a Gson
object and its method getAdapter(Class<T> type)
.
So your provided example would look like this:
Java Beans:
//Employee object class
@JsonAdapter(EmployeeAdapter.class)
public class Employee {
private int id;
private String name;
private String emailId;
private Address address;
..
}
//Address object class
@JsonAdapter(AddressAdapter.class)
public class Address {
private String address;
private String district;
private String city;
private String region;
private String postalCode;
private String country;
..
}
Type Adapters:
public class EmployeeAdapter extends TypeAdapter<Employee> {
@Override
public void write(JsonWriter out, Employee employee) throws IOException {
//
}
@Override
public Employee read(JsonReader jsonReader) throws IOException {
Employee employee = new Employee();
jsonReader.beginObject();
//read your Employee fields
TypeAdapter<Address> addressAdapter = new Gson().getAdapter(Address.class);
employee.setAddress(addressAdapter.read(jsonReader);
return employee;
}
}
public class AddressAdapter extends TypeAdapter<Address> {
@Override
public void write(JsonWriter out, Address address) throws IOException {
//
}
@Override
public Address read(JsonReader jsonReader) throws IOException {
Address address = new Address();
//read your Address fields
return address;
}
}
With this solution you have the benefits of a loosely coupled code, because of the only dependency in the Beans JsonAdapter
annotation.
Addtional you split the read / write logic for each Bean to its own TypeAdapter.
You can create a new instance of AddressAdapter
encapsulated in EmployeeAdapter
. Please go through following example.
public class EmployeeAdapter extends TypeAdapter<Employee> {
//private instance of address adapter
private AddressAdapter addressAdapter = new AddressAdapter();
@Override
public void write(JsonWriter out, Employee employee) throws IOException {
//TODO: do your stuff to Employee class
//manually do it to Address class
addressAdapter.write(out, employee.getAddress());
}
@Override
public Employee read(JsonReader jsonReader) throws IOException {
//your new instance of employee
Employee employee = new Employee();
//TODO: read logic for employee class using AddressAdapter for address json
//read from Address class
Address address = addressAdapter.read(jsonReader);//you may need only portion of address available, simply grab that string as same as other properties if needed
employee.setAddress(address);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.