【问题标题】:Java JSON serialization - best practiceJava JSON 序列化 - 最佳实践
【发布时间】:2011-09-24 15:28:35
【问题描述】:

我需要为一些对象实现 JSON 序列化,在与泛型集合集成时遇到了问题。

所有可序列化的类都实现了这个接口(JSONObject来自this库):

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

我的问题是:当我从 JSONObject 加载 AwesomeList 时,我需要创建它的元素,但这是不可能的,因为 java 禁止我写

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

我应该如何修改完成这项任务的方法?

【问题讨论】:

  • 老实说,我看不出它是如何与已知类型一起工作的。您是否将类名存储在 JSON 数据包中?
  • 不,每个对象都知道如何从 JSONObject 加载自己(它实际上只是关联数组)。我更新了帖子以显示我想做什么。

标签: java json design-patterns


【解决方案1】:

你绑定到这个库了吗? Google Gson 很受欢迎。我自己没有将它与泛型一起使用,但他们的首页说 Gson 认为对泛型的支持非常重要。

【讨论】:

  • gson 可以很好地处理泛型。
  • 上次我检查 gson 不处理循环引用.. 虽然更新可以解决这个问题.. 我发现 [link]jackson.codehaus.org 最好。查看我的这个问题,了解如何使用 gson 中的泛型进行 json 转换 [链接]stackoverflow.com/questions/5528385/json-conversion-using-gson
  • GSON的使用非常非常非常简单。
  • 如果你需要处理泛型、循环引用、接口、集合和定义了接口的映射(映射不是LinkedHashMap)等,请尝试使用json-io:github.com/jdereg/json-io
【解决方案2】:

正如其他人所暗示的,您应该考虑转储 org.json 的库。这些天它已经过时了,试图解决它的问题是浪费时间。

但是针对具体问题;类型变量 T 只是没有任何信息可以帮助您,因为它只是编译时信息。 相反,您需要传递实际的类(作为“Class cls”参数),然后您可以使用“cls.newInstance()”创建一个实例。

【讨论】:

    【解决方案3】:

    你试过 json-io (https://github.com/jdereg/json-io) 吗?

    该库允许您序列化/反序列化任何 Java 对象图,包括其中带有循环的对象图(例如,A->B、B->A)。它不需要您的类实现任何特定的接口或从任何特定的 Java 类继承。

    除了将 Java 序列化为 JSON(以及将 JSON 序列化为 Java)之外,您还可以使用它来格式化(漂亮打印)JSON:

    String niceFormattedJson = JsonWriter.formatJson(jsonString)
    

    【讨论】:

      【解决方案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
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-27
        • 2022-01-03
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多