web-dev-qa-db-fra.com

Java sérialisation JSON - meilleure pratique

J'ai besoin d'implémenter la sérialisation JSON pour certains objets, et j'ai rencontré un problème lors de l'intégration avec des collections génériques.

Toutes les classes sérialisables implémentent cette interface (JSONObject provient de la bibliothèque this ):

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

Le code de ma collection basé sur Java.util.list ressemble plus ou moins à ceci:

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
    }
}

Mon problème est: quand je charge AwesomeList depuis JSONObject, je dois créer ses éléments mais c'est impossible puisque Java m'interdit d'écrire

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

Comment dois-je modifier mon approche de cette tâche?

25
KCH

Êtes-vous lié à cette bibliothèque? Google Gson est très populaire. Je ne l'ai moi-même pas utilisé avec Generics mais leur première page indique que Gson considère le support pour Generics très important.

33
Miserable Variable

Comme d'autres l'ont laissé entendre, vous devriez envisager de vider la bibliothèque d'org.json. C'est à peu près obsolète de nos jours, et essayer de contourner ses problèmes est une perte de temps.

Mais à une question spécifique; la variable de type T n'a tout simplement aucune information pour vous aider, car ce n'est guère plus que des informations au moment de la compilation. Au lieu de cela, vous devez passer la classe réelle (en tant qu'argument 'Class cls'), et vous pouvez ensuite créer une instance avec 'cls.newInstance ()'.

4
StaxMan

Avez-vous essayé json-io ( https://github.com/jdereg/json-io )?

Cette bibliothèque vous permet de sérialiser/désérialiser n'importe quel graphique Java objet, y compris les graphiques objet avec des cycles en eux (par exemple, A-> B, B-> A). Il ne nécessite pas que vos classes implémenter une interface particulière ou hériter d'une classe particulière Java.

En plus de la sérialisation de Java vers JSON (et JSON vers Java), vous pouvez l'utiliser pour formater (jolie impression) JSON:

String niceFormattedJson = JsonWriter.formatJson(jsonString)
1
John DeRegnaucourt

Eh bien, lorsque vous l'écrivez dans un fichier, vous savez ce qu'est la classe T, vous pouvez donc la stocker dans dump. Ensuite, lorsque vous le relisez, vous pouvez l'appeler dynamiquement à l'aide de la réflexion.

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
        }
    }
1
mangoDrunk