Saeid
Saeid

Reputation: 448

How to use autobean for converting json to java class in GWT

I have a class Person in gwt and I have sent an instance of Person with servlet converted using Gson from server to client. But in the client side seems I can't use Gson. From what I read in forums it seems that the best way is using AutoBeans to convert Json to object Person again.

However in AutoBeans I can only use an interface. I will appreciate if anyone can help me write it.

A json example I get from server and want to convert to Person class again:

{"name":"aaa","family":"fff","username":"uuu","age":20,"phones":[{"id":0,"phoneNumber":"0911111"}],"relatives":[null]}

public class Person implements Serializable {
   private String name;
   private String family;
   private String username;
   private int age;
   private List<Phone> phones;
   private List<Person> relatives;

   public Person() {
   }

   public Person(String name, String family, String username, int age, List<Phone> phones, List<Person> relatives) {
      this.name = name;
      this.family = family;
      this.username = username;
      this.age = age;
      this.phones = phones;
      this.relatives = new ArrayList<Person>();
      this.relatives = relatives;
   }

   public void addPhone(Phone p) {
      phones.add(p);
   }

   public String getName() {
      return this.name;
   }

   public String getFamily() {
      return this.family;
   }

   public int getAge() {
      return this.age;
   }

   public String getUsername() {
      return this.username;
   }

   public List<Phone> getNumbers() {
      return this.phones;
   }

   public List<Person> getRelatives() {
      return this.relatives;
   }

   public String getAllNumbers() {
      return Phone.convertPhonesToText(phones);
   }

   public static Person findPerson(List<Person> personList, String username) {
      // .....
   }

   public static List<Person> convertTextToPersons(List<Person> personList, String personsText) {
      // .....
   }

   public String convertPersonsToText() {
      // ....
   }
}

Upvotes: 1

Views: 705

Answers (1)

Ignacio Baca
Ignacio Baca

Reputation: 1578

Yep, as commented by Tobika the other answer indicates that AutoBeans requires an Interface. AutoBeans feets better if you use it on both sides, client and server side and you define all your models as interfaces.

If you want to use your class models, you can use GWT Jackson which is pretty similar to AutoBeans but it uses your models, binding the json to your model (like other server side libraries; jackson, gson, etc): https://github.com/nmorel/gwt-jackson

public static interface PersonMapper extends ObjectMapper<Person> {}

@Override public void onModuleLoad() {
    PersonMapper mapper = GWT.create(PersonMapper.class);

    String json = mapper.write(new Person("John", "Doe"));
    GWT.log( json ); // > {"firstName":"John","lastName":"Doe"}

    Person person = mapper.read(json);
    GWT.log(person.getFirstName() + " " + person.getLastName());
}

Alternatively, you can use just plain GWT with JsInterop. This has many limitations but even with this limitation, it is a pretty good option. This is my favorite option if you can avoid inheritance in your DTOs. But this has the big advantage of being super lightweight (actually zero overhead mapping overhead and zero code overhead as it uses native parsing and no copies, accesing directly to the parsed json object). Limitations: cannot use inheritance, "broken type system" (all X instanceof SomeDtoType returns always true as all DTOs are of type Object wich makes sense because we are actually using the parsed JSON), cannot use collections only native arrays (but thanks to java8 Stream this should not be a problem, whatever you want to do with start with Stream.of(arr)), and only Double and Boolean boxed types supported (not supported any fancy type like Date or BigInteger, not supported long/Long...).

@JsType(isNative=true, package=GLOBAL, name="Object") final class Person {
    // you can use getter/setter but as this class is final DTO adds no value
    public String firstName; public String lastName; public Phome[] numbers;
    // you can add some helper methods, don't forget to skip serialization!
    public final @JsOverlay @JsonIgnore List<Phone> getNumberList() {
        return Stream.of(numbers).collect(Collectors.toList());
    }
}

@JsType(isNative=true, package=GLOBAL, name="Object) final class Phone {
    public String number;
}

@JsMethod(namespace = "JSON") public static native <T> T parse(String text);

@Override public void onModuleLoad() {
    Person person = parse("{\"firstName\":\"John\",\"lastName\":\"Doe\"}");
    GWT.log(person.firstName + " " + person.lastName);
}

These simple and limited DTOs are more a DTO scheme than a type. But has a big advantage, this DTOs works out of the box with most of the server side parsers. Jackson and GSON will encode and parse without any configuration.

Upvotes: 1

Related Questions