Java JSON сериализация - лучшая практика - PullRequest
25 голосов
/ 24 сентября 2011

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

Все сериализуемые классы реализуют этот интерфейс (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);

Как я долженизменить мой подход к этой задаче?

Ответы [ 4 ]

33 голосов
/ 24 сентября 2011

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

4 голосов
/ 02 октября 2011

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

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

1 голос
/ 24 февраля 2014

Испытали json-io (https://github.com/jdereg/json-io)?

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

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

String niceFormattedJson = JsonWriter.formatJson(jsonString)
0 голосов
/ 24 сентября 2011

Ну, когда вы записываете это в файл, вы знаете, что такое класс 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
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...