Сериализация Java JSON - лучшая практика

Мне нужно реализовать сериализацию JSON для некоторых объектов, и я столкнулся с проблемой, когда дело дошло до интеграции с коллекциями generic.

Все сериализуемые классы реализуют этот интерфейс (JSONObject исходит из этой библиотеки):

interface JSONSerializable{
    public JSONObject dump() throws JSONException //serializes object
    public void load(JSONObject obj) throws JSONException //deserializes object
}

Код моей коллекции на основе java.util.list выглядит примерно так:

class AwesomeList<T extends JSONSerializable> implements JSONSerializable{
    private LinkedList<T> items = new LinkedList<T>();
    ...
    ...

    public JSONObject dump() throws JSONException {
        JSONObject result = new JSONObject();
        JSONArray a = new JSONArray();
        for(T i : items){
            a.put(i.dump());
        }
        result.put("items", a);
        return result;
    }

    public void load(JSONObject obj) throws JSONException{
        //here is my problem
    }
}

Моя проблема: когда я загружаю AwesomeList из JSONObject, мне нужно создать его элементы, но это невозможно, поскольку java запрещает мне писать

T newItem = new T();
newItem.load(obj);

Как мне изменить свой подход к этой задаче?

Ответ 1

Вы привязаны к этой библиотеке? Google Gson очень популярен. Я сам не использовал его с Generics, но их первая страница говорит, что Gson считает, что поддержка Generics очень важна.

Ответ 2

Как намекают другие, вы должны подумать о демпинге библиотеки org.json. Это в значительной степени устарело в наши дни, и попытка обойти его проблемы - пустая трата времени.

Но к конкретному вопросу; тип переменной T просто не имеет никакой информации, которая вам поможет, так как это немного больше, чем информация времени компиляции. Вместо этого вам нужно передать фактический класс (как аргумент класса cls), и затем вы можете создать экземпляр с 'cls.newInstance()'.

Ответ 3

Хотя вы решили использовать Gson (хорошее решение).

Вот быстрый фрагмент для u для проблемы с ur

public void load(JSONObject result) throws JSONException{
    JSONArray a = (JSONArray) result.get("items");
    for (int i = 0; i < a.length(); i++) {
        T t = (T)a.get(i);
        items.add(t);
    }
}

Я не тестировал его, но он должен работать, я считаю.

Ответ 4

Ну, когда вы записываете файл в файл, вы знаете, что такое класс T, поэтому вы можете сохранить его в dump. Затем, читая его обратно, вы можете динамически называть его с помощью отражения.

public JSONObject dump() throws JSONException {
    JSONObject result = new JSONObject();
    JSONArray a = new JSONArray();
    for(T i : items){
        a.put(i.dump());
        // inside this i.dump(), store "class-name"
    }
    result.put("items", a);
    return result;
}

public void load(JSONObject obj) throws JSONException {
    JSONArray arrayItems = obj.getJSONArray("items");
    for (int i = 0; i < arrayItems.length(); i++) {
        JSONObject item = arrayItems.getJSONObject(i);
        String className = item.getString("class-name");
        try {
            Class<?> clazzy = Class.forName(className);
            T newItem = (T) clazzy.newInstance();
            newItem.load(obj);
            items.add(newItem);
        } catch (InstantiationException e) {
            // whatever
        } catch (IllegalAccessException e) {
            // whatever
        } catch (ClassNotFoundException e) {
            // whatever
        }
    }

Ответ 5

Попробуйте json-io (https://github.com/jdereg/json-io)?

Эта библиотека позволяет сериализовать/десериализовать любой графический объект Java, включая графические объекты с циклами в них (например, A- > B, B- > A). Это не требует, чтобы ваши классы реализовали какой-либо конкретный интерфейс или наследовали какой-либо конкретный Java-класс.

В дополнение к сериализации Java для JSON (и JSON для Java) вы можете использовать его для форматирования (довольно печатать) JSON:

String niceFormattedJson = JsonWriter.formatJson(jsonString)