вторник, 4 марта 2014 г.

Сериализация java bean в JSON

Давно задумывался над сериализацией JSON в java сущности и обратно.
Чтобы красиво, грациозно, и главное - производительно. Еще одно требование, чтобы сериализация производилась в строки, это наиболее универсальный формат для межсистемного взаимодействия. Пo этой причине Protobuf не рассматривал. Как правило использовал org.codehaus.jettison.json.JSONObject и ручную сериализацию. Внутри него используется LinkedHashMap поэтому операции с полями происходят быстро.

public class Geo
{

    private static final String LAT_FIELD = "lat";
    private static final String LON_FIELD = "lon";

    private float lat;
    private float lon;

    public String toJSON()
    {
        JSONObject json = new JSONObject();

        try {
            json.put(LAT_FIELD, lat);
            json.put(LON_FIELD, lon);
        } catch (JSONException e) {
            LOG.error("Cannot convert Geo object into json.", e);
        }

        return json.toString();
    }


    public static Geo fromJSON(final String json) throws JSONException
    {
        JSONObject jsonObject = new JSONObject(json);
        Geo geo = new Geo();

        geo.setLon((float) jsonObject.optDouble(LON_FIELD, Float.NaN));
        geo.setLat((float) jsonObject.optDouble(LAT_FIELD, Float.NaN));

        return geo;
    }
}


Надо ли говорить, что при большом количестве полей, такой подход адски неудобен.
Не красиво и трудозатратно, зато сносно, с точки зрения производительности, плюс поддержка валидации.
Всегда знал о такой штуке как com.google.gson.Gson но обходил его стороной, т.к он использует рефлексию, казалось что это снизит производительность.
Но красота использования Gson,

public class Geo
{
    private float lat;
    private float lon;

    public String toJSON()
    {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

    public static Geo fromJSON(final String json)
    {
        Gson gson = new Gson();
        return gson.fromJson(json, Geo.class);
    }
}

...и безобразность ручной сериализации не давали покоя.
Решил на днях замерить производительность этих двух подходов.
Всё как всегда, цикл на миллион, и время в наносекундах.

Результаты:

Сериализация сущности в строку
Gson              4088893178
JSONObject  4543766682

Десериализация из строки:
Gson              2728182025
JSONObject  4180603421

Приятно удивлен производительностью Gson, оказывается в некоторых случаях она в полтора раза выше. Радости нет предела. Теперь буду пользоваться им.