将任意json数据读取到javafx树视图,并仅显示其中任何数组的第一个元素

将任意json数据读取到javafx树视图,并仅显示其中任何数组的第一个元素,json,javafx,treeview,gson,Json,Javafx,Treeview,Gson,我需要在javafx树视图上显示一个json文件,json的结构未知。如网站: 我向用户显示树以选择值的路径(如xml的xpath),因此如果json太大,我只需要显示json中任何数组的第一个元素 例如,原始数据为: { name:"tom", schools:[ { name:"school1", tags:["maths","english"] }, {

我需要在javafx树视图上显示一个json文件,json的结构未知。如网站: 我向用户显示树以选择值的路径(如xml的xpath),因此如果json太大,我只需要显示json中任何数组的第一个元素

例如,原始数据为:

{
    name:"tom",
    schools:[
        {
            name:"school1",
            tags:["maths","english"]
        },
        {
            name:"school2",
            tags:["english","biological"]
        },
    ]
}
我想展示:


同样:json的结构未知,这只是一个示例。

除了递归处理json并基于元素信息创建
TreeItem
结构之外,没有其他选择

(可能有更好的方法添加符号,但我没有找到合适的图标。)

private静态最终字符串输入=“{\n”
+名称:\'tom\',\n
+“学校:[\n”
+“{\n”
+名称:\'school1\',\n
+标记:[“数学\”,“英语\]”\n
+},\n
+“{\n”
+名称:\'school2\',\n
+“标记:[\'english\',\'biological\']\n”
+},\n
+“]\n”
+ "}";
私有静态最终图像JSON_Image=新图像(“https://i.stack.imgur.com/1slrh.png");
私有静态void prependString(树项,字符串){
字符串val=item.getValue().text;
item.getValue().text=(val==null)
一串
:字符串+“:”+val);
}
私有枚举类型{
对象(新矩形2D(45,52,16,18)),
阵列(新矩形2D(61,88,16,18)),
属性(新矩形2D(31,13,16,18));
私有最终矩形2D视口;
私有类型(矩形2D视口){
this.viewport=视口;
}
}
私有静态最终类值{
私有字符串文本;
私有最终类型;
公共值(类型){
this.type=type;
}
公共值(字符串文本,类型){
this.text=文本;
this.type=type;
}
}
私有静态树Item createTree(JsonElement元素){
if(element.isJsonNull()){
返回新的TreeItem(新值(“null”,Type.PROPERTY));
}else if(element.isJsonPrimitive()){
JsonPrimitive=element.getAsJsonPrimitive();
返回新的TreeItem(新值(primitive.isString()
?'“'+基元。getAsString()+'”
:primitive.getAsString(),Type.PROPERTY));
}else if(element.isJsonArray()){
JsonArray数组=element.getAsJsonArray();
TreeItem item=newtreeitem(新值(Type.ARRAY));
//对于(inti=0,max=Math.min(1,array.size());i新建TreeCell(){
私人最终影像视图;
{
imageView=新的imageView(JSON_图像);
imageView.setFitHeight(18);
imageView.setFitWidth(16);
imageView.setPreserveRatio(真);
设置图形(图像视图);
}
@凌驾
受保护的void updateItem(值项,布尔值为空){
super.updateItem(项,空);
if(空| |项==null){
setText(“”);
imageView.setVisible(false);
}否则{
setText(item.text);
imageView.setVisible(true);
设置视口(item.type.viewport);
}
}
});
最终场景=新场景(treeView);
初级阶段。场景(场景);
primaryStage.show();
}

太好了!这就是我需要的。我可能想过如何写,但没有写出来。但我想知道你是如何制作方括号和花括号的?图标还是符号?但我找不到符号。如果只读取数组的第一个元素,可能更符合问题。我找不到符号,所以它使用了你的屏幕n单击并调整视口以显示该图像的适当部分。这不是最佳解决方案,您可能应该创建自己的图像或使用一些
形状(
文本
/
矩形
)为了确保不侵犯任何版权…如果我想在树项目中添加一个复选框,并且仍然显示图片,我该怎么办?修改
TreeCell
实现。这是一个新问题,但无法在注释中正确回答。
private static final String INPUT = "{\n"
        + "    name:\"tom\",\n"
        + "    schools:[\n"
        + "        {\n"
        + "            name:\"school1\",\n"
        + "            tags:[\"maths\",\"english\"]\n"
        + "        },\n"
        + "        {\n"
        + "            name:\"school2\",\n"
        + "            tags:[\"english\",\"biological\"]\n"
        + "        },\n"
        + "    ]\n"
        + "}";

private static final Image JSON_IMAGE = new Image("https://i.stack.imgur.com/1slrh.png");

private static void prependString(TreeItem<Value> item, String string) {
    String val = item.getValue().text;
    item.getValue().text = (val == null
            ? string
            : string + " : " + val);
}

private enum Type {
    OBJECT(new Rectangle2D(45, 52, 16, 18)),
    ARRAY(new Rectangle2D(61, 88, 16, 18)),
    PROPERTY(new Rectangle2D(31, 13, 16, 18));

    private final Rectangle2D viewport;

    private Type(Rectangle2D viewport) {
        this.viewport = viewport;
    }

}

private static final class Value {

    private String text;
    private final Type type;

    public Value(Type type) {
        this.type = type;
    }

    public Value(String text, Type type) {
        this.text = text;
        this.type = type;
    }

}

private static TreeItem<Value> createTree(JsonElement element) {
    if (element.isJsonNull()) {
        return new TreeItem<>(new Value("null", Type.PROPERTY));
    } else if (element.isJsonPrimitive()) {
        JsonPrimitive primitive = element.getAsJsonPrimitive();
        return new TreeItem<>(new Value(primitive.isString()
                ? '"' + primitive.getAsString() + '"'
                : primitive.getAsString(), Type.PROPERTY));
    } else if (element.isJsonArray()) {
        JsonArray array = element.getAsJsonArray();
        TreeItem<Value> item = new TreeItem<>(new Value(Type.ARRAY));
       // for (int i = 0, max = Math.min(1, array.size()); i < max; i++) {
        for (int i = 0, max = array.size(); i < max; i++) {
            TreeItem<Value> child = createTree(array.get(i));
            prependString(child, Integer.toString(i));
            item.getChildren().add(child);
        }
        return item;
    } else {
        JsonObject object = element.getAsJsonObject();
        TreeItem<Value> item = new TreeItem<>(new Value(Type.OBJECT));
        for (Map.Entry<String, JsonElement> property : object.entrySet()) {
            TreeItem<Value> child = createTree(property.getValue());
            prependString(child, property.getKey());
            item.getChildren().add(child);
        }
        return item;
    }
}

@Override
public void start(Stage primaryStage) {
    JsonParser parser = new JsonParser();
    JsonElement root = parser.parse(INPUT);

    TreeItem<Value> treeRoot = createTree(root);
    TreeView<Value> treeView = new TreeView<>(treeRoot);
    treeView.setCellFactory(tv -> new TreeCell<Value>() {
        private final ImageView imageView;

        {
            imageView = new ImageView(JSON_IMAGE);
            imageView.setFitHeight(18);
            imageView.setFitWidth(16);
            imageView.setPreserveRatio(true);
            setGraphic(imageView);
        }

        @Override
        protected void updateItem(Value item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                setText("");
                imageView.setVisible(false);
            } else {
                setText(item.text);
                imageView.setVisible(true);
                imageView.setViewport(item.type.viewport);
            }
        }


    });

    final Scene scene = new Scene(treeView);

    primaryStage.setScene(scene);
    primaryStage.show();
}