JavaFX TreeView JSON Ex/通过GSON导入

JavaFX TreeView JSON Ex/通过GSON导入,java,json,javafx,treeview,gson,Java,Json,Javafx,Treeview,Gson,我正在寻找一种将JavaFXTreeView导出为JSON的方法。为了简化整个过程,我使用了GSON。它可以很好地导出树元素的值,但是当我尝试使用整个树时,它的结尾是堆栈溢出。我相信这与父/子属性有关。是否有方法阻止GSON导出此属性 我该如何再次导入整个内容?我无法导入我的简单对象,因为GSON无法处理属性。您需要使用自定义类型适配器。此外,您可以通过使用循环而不是递归来防止堆栈溢出: public class TreeItemTypeAdapter<T> extends Type

我正在寻找一种将JavaFXTreeView导出为JSON的方法。为了简化整个过程,我使用了GSON。它可以很好地导出树元素的值,但是当我尝试使用整个树时,它的结尾是堆栈溢出。我相信这与父/子属性有关。是否有方法阻止GSON导出此属性


我该如何再次导入整个内容?我无法导入我的简单对象,因为GSON无法处理属性。

您需要使用自定义类型适配器。此外,您可以通过使用循环而不是递归来防止堆栈溢出:

public class TreeItemTypeAdapter<T> extends TypeAdapter<TreeItem<T>> {

    private Gson gson;

    public void setGson(Gson gson) {
        this.gson = gson;
    }

    private final Class<T> valueClass;

    public TreeItemTypeAdapter(Class<T> valueClass) {
        if (valueClass == null) {
            throw new IllegalArgumentException();
        }
        this.valueClass = valueClass;
    }

    public static TreeItemTypeAdapter<String> createStringTreeItemAdapter() {
        return new TreeItemTypeAdapter<>(String.class);
    }

    private void writeValue(JsonWriter writer, T t) throws IOException {
        if (gson == null) {
            writer.value(Objects.toString(t, null));
        } else {
            gson.toJson(t, valueClass, writer);
        }
    }

    private T readValue(JsonReader reader) throws IOException {
        if (gson == null) {
            Object value = reader.nextString();
            return (T) value;
        } else {
            return gson.fromJson(reader, valueClass);
        }
    }

    @Override
    public void write(JsonWriter writer, TreeItem<T> t) throws IOException {
        writer.beginObject().name("value");
        writeValue(writer, t.getValue());
        writer.name("children").beginArray();
        LinkedList<Iterator<TreeItem<T>>> iterators = new LinkedList<>();
        iterators.add(t.getChildren().iterator());
        while (!iterators.isEmpty()) {
            Iterator<TreeItem<T>> last = iterators.peekLast();
            if (last.hasNext()) {
                TreeItem<T> ti = last.next();
                writer.beginObject().name("value");
                writeValue(writer, ti.getValue());
                writer.name("children").beginArray();
                iterators.add(ti.getChildren().iterator());
            } else {
                writer.endArray().endObject();
                iterators.pollLast();
            }
        }
    }

    @Override
    public TreeItem<T> read(JsonReader reader) throws IOException {
        if (gson == null && !valueClass.getName().equals("java.lang.String")) {
            throw new IllegalStateException("cannot parse classes other than String without gson provided");
        }
        reader.beginObject();
        if (!"value".equals(reader.nextName())) {
            throw new IOException("value expected");
        }
        TreeItem<T> root = new TreeItem<>(readValue(reader));
        TreeItem<T> item = root;
        if (!"children".equals(reader.nextName())) {
            throw new IOException("children expected");
        }
        reader.beginArray();
        int depth = 1;
        while (depth > 0) {
            if (reader.hasNext()) {
                reader.beginObject();
                if (!"value".equals(reader.nextName())) {
                    throw new IOException("value expected");
                }
                TreeItem<T> newItem = new TreeItem<>(readValue(reader));
                item.getChildren().add(newItem);
                item = newItem;
                if (!"children".equals(reader.nextName())) {
                    throw new IOException("children expected");
                }
                reader.beginArray();
                depth++;
            } else {
                depth--;
                reader.endArray();
                reader.endObject();
                item = item.getParent();
            }

        }
        return root;
    }

}
公共类TreeItemTypeAdapter扩展了TypeAdapter{
私人Gson;
公共无效设置(Gson Gson){
this.gson=gson;
}
私有最终类valueClass;
public TreeItemTypeAdapter(类值类){
如果(valueClass==null){
抛出新的IllegalArgumentException();
}
this.valueClass=valueClass;
}
公共静态树类型适配器createStringTreeItemAdapter(){
返回新的TreeItemTypeAdapter(String.class);
}
私有void writeValue(JsonWriter writer,T)抛出IOException{
if(gson==null){
writer.value(Objects.toString(t,null));
}否则{
toJson(t,valueClass,writer);
}
}
私有T readValue(JsonReader)引发IOException{
if(gson==null){
对象值=reader.nextString();
返回(T)值;
}否则{
返回gson.fromJson(读取器,valueClass);
}
}
@凌驾
public void write(JsonWriter writer,TreeItem t)引发IOException{
writer.beginObject().name(“值”);
writeValue(writer,t.getValue());
writer.name(“children”).beginArray();
LinkedList迭代器=新建LinkedList();
add(t.getChildren().iterator());
而(!iterators.isEmpty()){
迭代器last=迭代器.peek last();
if(last.hasNext()){
TreeItem ti=last.next();
writer.beginObject().name(“值”);
writeValue(writer,ti.getValue());
writer.name(“children”).beginArray();
迭代器.add(ti.getChildren().iterator());
}否则{
writer.endArray().endObject();
iterators.pollLast();
}
}
}
@凌驾
public TreeItem read(JsonReader reader)引发IOException{
if(gson==null&&!valueClass.getName().equals(“java.lang.String”)){
抛出新的IllegalStateException(“在未提供gson的情况下无法解析字符串以外的类”);
}
reader.beginObject();
如果(!“value”.equals(reader.nextName())){
抛出新IOException(“预期值”);
}
TreeItem root=newtreeitem(readValue(reader));
TreeItem项目=根;
if(!“children.equals(reader.nextName())){
抛出新IOException(“预期的子项”);
}
reader.beginArray();
int深度=1;
而(深度>0){
if(reader.hasNext()){
reader.beginObject();
如果(!“value”.equals(reader.nextName())){
抛出新IOException(“预期值”);
}
TreeItem newItem=newtreeitem(readValue(reader));
item.getChildren().add(newItem);
项目=新项目;
if(!“children.equals(reader.nextName())){
抛出新IOException(“预期的子项”);
}
reader.beginArray();
深度++;
}否则{
深度--;
reader.endArray();
reader.endObject();
item=item.getParent();
}
}
返回根;
}
}
publicstaticvoidmain(字符串[]args){
TreeItem ti=新TreeItem(“你好世界”);
TreeItem ti2=新的TreeItem(“42”);
TreeItem ti3=新TreeItem(“Foo”);
TreeItem ti4=新的TreeItem(“条形”);
ti.getChildren().addAll(ti2,ti3);
ti2.getChildren().add(ti4);
TreeItemTypeAdapter=新的TreeItemTypeAdapter(String.class);
Gson Gson=new GsonBuilder().registerTypeAdapter(TreeItem.class,adapter).create();
适配器。setGson(gson);
System.out.println(gson.toJson(ti));
System.out.println(toString(gson.fromJson(“{\'value\”:\'Hello world\”,\'children\”:[{\'value\”:\'42\,\'children\”:[{\'value\”:\'Bar\,\'children\:[]},{\'value\:\'Foo\,\'children\:[]},
TreeItem.class));
}
私有静态字符串到字符串(TreeItem ti){
StringBuilder sb=new StringBuilder(“TreeItem[value:\”).append(ti.getValue()).append(“\”子项[”);
布尔notFirst=false;
for(TreeItem i:(List)ti.getChildren(){
如果(不是第一个){
某人加上(“,”);
}否则{
notFirst=true;
}
某人附加(toString(i));
}
返回sb.append(“]]”);
}
public static void main(String[] args) {
    TreeItem<String> ti = new TreeItem<>("Hello world");
    TreeItem<String> ti2 = new TreeItem<>("42");
    TreeItem<String> ti3 = new TreeItem<>("Foo");
    TreeItem<String> ti4 = new TreeItem<>("Bar");
    ti.getChildren().addAll(ti2, ti3);
    ti2.getChildren().add(ti4);

    TreeItemTypeAdapter<String> adapter = new TreeItemTypeAdapter<>(String.class);
    Gson gson = new GsonBuilder().registerTypeAdapter(TreeItem.class, adapter).create();
    adapter.setGson(gson);

    System.out.println(gson.toJson(ti));
    System.out.println(toString(gson.fromJson("{\"value\":\"Hello world\",\"children\":[{\"value\":\"42\",\"children\":[{\"value\":\"Bar\",\"children\":[]}]},{\"value\":\"Foo\",\"children\":[]}]}",
            TreeItem.class)));
}

private static String toString(TreeItem ti) {
    StringBuilder sb = new StringBuilder("TreeItem [ value: \"").append(ti.getValue()).append("\" children [");
    boolean notFirst = false;
    for (TreeItem i : (List<TreeItem>) ti.getChildren()) {

        if (notFirst) {
            sb.append(",");
        } else {
            notFirst = true;
        }
        sb.append(toString(i));
    }
    return sb.append("]]").toString();
}