简体   繁体   English

使用gson TypeAdapter将嵌套的JSON转换为嵌套的Java对象

[英]Convert nested JSON to nested Java object using gson TypeAdapter

I am trying to use google gson TypeAdapter for converting nested JSON into nested Java object having implementation of TypeAdapter for each class. 我正在尝试使用google gson TypeAdapter将嵌套的JSON转换为嵌套的Java对象,并为每个类实现TypeAdapter。 But I don't want to write complete read() method logic in single adapter class. 但我不想在单个适配器类中编写完整的read()方法逻辑。 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. 对于小型嵌套对象,可以在单个适配器中使用逻辑,但对于大对象(每个类中有超过10-15个字段),它并不好。

[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. 例如,json键看起来与类属性相同,但实际上我将获得输入为hyphen-separated-small-case键而不是Camel case键。 So my json and java classes attribute names will not be same hence I have to write my custom logic for mapping. 所以我的json和java类属性名称不一样,因此我必须编写自定义逻辑进行映射。

Eg Sample Json input : 例如样品Json输入:

{
  "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 : Java bean如下:

//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. 我想有两个不同的适配器,并在read()方法中集成多个适配器。

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? 如何在EmployeeAdapter中使用AddressAdapter?

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) . 您可以借助Gson对象及其方法getAdapter(Class<T> type)获取新的TypeAdapter<T>实例。

So your provided example would look like this: 所以你提供的例子如下所示:

Java Beans: Java豆:

//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. 使用此解决方案,您可以获得松散耦合的代码,因为Beans JsonAdapter注释中只有依赖JsonAdapter
Addtional you split the read / write logic for each Bean to its own TypeAdapter. Addtional您将每个Bean的读/写逻辑拆分为它自己的TypeAdapter。

You can create a new instance of AddressAdapter encapsulated in EmployeeAdapter . 您可以创建封装在EmployeeAdapterAddressAdapter的新实例。 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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM