Как сериализовать такой пользовательский тип в JSON с Google-GSON? - PullRequest
0 голосов
/ 20 декабря 2011

Во-первых, у меня есть очень простой Java-бин, который можно легко сериализовать в 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" }

Затем, чтобы такие бины имели некоторые динамические значения, я создаю базовый класс 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 сначала сериализовать свойства, а затем данные в карте.

Ответы [ 2 ]

6 голосов
/ 23 декабря 2011

Что я делаю сейчас, это создание собственного сериализатора:

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.

4 голосов
/ 22 декабря 2011

На самом деле, вы должны ожидать, что 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 соответствующим образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...