Jackson/Gson serialize and deserialize JavaFX Properties to json

colmulhall :

I have added a BooleanProperty into a DAO class which is to be serializes into JSON and send across to a server to be saved in a MySQL database. The reason I am using the BooleanProperty is because I want to use data binding for the 'isActive' field in my JavaFX desktop application.

The class to be serialized:

package com.example.myapplication

import lombok.Data;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;

@Data
public class MyDAO {
    private int id;
    private String firstName;
    private String lastname;
    private final BooleanProperty isActive = new SimpleBooleanProperty();
}

I am serializing to JSON using Gson:

StringEntity entity = new StringEntity(new Gson().toJson(myDTO), "UTF-8");

When this gets serialized to JSON, it looks like this:

{
   "id":0,
   "first_name":"Joe",
   "last_name":"Bloggs",
   "is_active":{
      "name":"",
      "value":false,
      "valid":true

   }
}

This is causing problems on the server when deserializing (using Jackson), as the server expects a boolean value to correspond with what will be saved in the database. Is there a way to just get the true/false value deserialized from the BooleanProperty?

This is what I would like to see in the server:

{
   "id":0,
   "first_name":"Joe",
   "last_name":"Bloggs",
   "is_active": false,
}
Michał Ziober :

Your client app uses Gson to serialise POJO to JSON and server app uses Jackson to deserialise JSON back to POJO. In both cases these two libraries by default serialise provided classes as regular POJO-s. In your POJO you use JavaFX Properties which are wrappers for values with extra functionality. When you serialise POJO to JSON sometimes you need to hide internal implementation of POJO and this is why you should implement custom serialiser or use FX Gson library.

1. Custom serialiser

To write custom serialiser you need to implement com.google.gson.JsonSerializer interface. Below you can find an example hot it could look like:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Data;

import java.lang.reflect.Type;

public class GsonApp {

    public static void main(String[] args) {
        MyDAO myDAO = new MyDAO();
        myDAO.setId(1);
        myDAO.setFirstName("Vika");
        myDAO.setLastname("Zet");
        myDAO.getIsActive().set(true);

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(BooleanProperty.class, new BooleanPropertySerializer())
                .setPrettyPrinting().create();
        System.out.println(gson.toJson(myDAO));
    }

}

class BooleanPropertySerializer implements JsonSerializer<BooleanProperty> {
    @Override
    public JsonElement serialize(BooleanProperty src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src.getValue());
    }
}

@Data
class MyDAO {
    private int id;
    private String firstName;
    private String lastname;
    private final BooleanProperty isActive = new SimpleBooleanProperty();
}

Above code prints:

{
  "id": 1,
  "firstName": "Vika",
  "lastname": "Zet",
  "isActive": true
}

2. FX Gson

In case you use many types from javafx.beans.property.* package good idea would be to use FX Gson library which implement custom serialisers for most used types. You just need to add one extra dependency to your Maven POM file:

<dependency>
    <groupId>org.hildan.fxgson</groupId>
    <artifactId>fx-gson</artifactId>
    <version>3.1.2</version>
</dependency>

Example usage:

import com.google.gson.Gson;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Data;
import org.hildan.fxgson.FxGson;

public class GsonApp {

    public static void main(String[] args) {
        MyDAO myDAO = new MyDAO();
        myDAO.setId(1);
        myDAO.setFirstName("Vika");
        myDAO.setLastname("Zet");
        myDAO.getIsActive().set(true);

        Gson gson = FxGson.coreBuilder().setPrettyPrinting().create();
        System.out.println(gson.toJson(myDAO));
    }

}

Above code prints:

{
  "id": 1,
  "firstName": "Vika",
  "lastname": "Zet",
  "isActive": true
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=19487&siteId=1