【问题标题】:How to serialize such a custom type to json with google-gson?如何使用 google-gson 将这种自定义类型序列化为 json?
【发布时间】:2011-12-20 08:25:33
【问题描述】:

首先,我有一个非常简单的java bean,可以很容易地序列化为json:

class Node {
    private String text;
    // getter and setter
}

Node node = new Node();
node.setText("Hello");

String json = new Gson().toJson(node);
// json is { text: "Hello" }

然后为了让这样的bean有一些动态值,所以我创建了一个“WithData”基类:

Class WithData {
    private Map<String, Object> map = new HashMap<String, Object>();
    public void setData(String key, Object value) { map.put(key, value); }
    public Object getData(String key) = { return map.get(key); }
}

class Node extends WithData {
    private String text;
    // getter and setter
}

现在我可以为节点设置更多数据:

Node node = new Node();
node.setText("Hello");
node.setData("to", "The world");

但是Gson会忽略“to”,结果还是{ text: "Hello" }。我希望它是:{ text: "Hello", to: "The world" }

有没有办法为WithData 类型编写一个序列化程序,所有类扩展它不仅会生成自己的json 属性,还会生成map 中的数据?

我尝试实现一个自定义的序列化器,但是失败了,因为我不知道如何让Gson先序列化属性,再序列化map中的数据。

【问题讨论】:

  • 您是否尝试公开您的地图字段?
  • 没用,希望map的key是json的key

标签: json serialization gson


【解决方案1】:

我现在要做的是创建一个自定义序列化程序:

public static class NodeSerializer implements JsonSerializer<Node> {
    public JsonElement serialize(Node src,
            Type typeOfSrc, JsonSerializationContext context) {
        JsonObject obj = new JsonObject();
        obj.addProperty("id", src.id);
        obj.addProperty("text", src.text);
        obj.addProperty("leaf", src.leaf);
        obj.addProperty("level", src.level);
        obj.addProperty("parentId", src.parentId);
        obj.addProperty("order", src.order);
        Set<String> keys = src.getDataKeys();
        if (keys != null) {
            for (String key : keys) {
                obj.add(key, context.serialize(src.getData(key)));
            }
        }
        return obj;
    };
}

然后使用GsonBuilder进行转换:

Gson gson = new GsonBuilder().
    registerTypeAdapter(Node.class, new NodeSerializer()).create();

Tree tree = new Tree();
tree.addNode(node1);
tree.addNode(node2);

gson.toJson(tree);

然后树中的节点将按我的预期进行转换。唯一无聊的是我每次都需要创建一个特殊的Gson

【讨论】:

    【解决方案2】:

    实际上,您应该期望Node:WithData 序列化为

    {
      "text": "Hello",
      "map": {
        "to": "the world"
      }
    }
    

    (即开启了“漂亮打印”)

    当我尝试您的示例时,我能够获得该序列化。这是我的确切代码

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    
    import java.net.MalformedURLException;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class Class1 {
    
      public static void main(String[] args) throws MalformedURLException {
        GsonBuilder gb = new GsonBuilder();
        Gson g = gb.setPrettyPrinting().create();
        
        Node n = new Node();
        n.setText("Hello");
        n.setData("to", "the world");
        
        System.out.println(g.toJson(n));
      }
      private static class WithData {
        private Map<String, Object> map = new HashMap<String, Object>();
        public void setData(String key, Object value) { map.put(key, value); }
        public Object getData(String key) { return map.get(key); }
      }
      private static class Node extends WithData {
        private String text;
        public Node() { }
        public String getText() {return text;}
        public void setText(String text) {this.text = text;}
      }
    }
    

    我使用 JDK (javac) 进行编译 - 这很重要,因为其他编译器(包含在某些 IDE 中的编译器)可能会删除 Gson 在优化或混淆过程中所依赖的信息。

    以下是我使用的编译和执行命令:

    “C:\Program Files\Java\jdk1.6.0_24\bin\javac.exe”-classpath gson-2.0.jar Class1.java

    "C:\Program Files\Java\jdk1.6.0_24\bin\java.exe" -classpath .;gson-2.0.jar Class1

    出于本次测试的目的,我将 Gson jar 文件放在与测试类文件相同的文件夹中。

    请注意,我使用的是 Gson 2.0; 1.x 的行为可能会有所不同。

    您的 JDK 可能安装在与我不同的位置,因此如果您使用这些命令,请务必根据需要调整 JDK 的路径。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      相关资源
      最近更新 更多