Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在YAML嵌套数据中搜索值_Java_Xpath_Jackson_Yaml_Snakeyaml - Fatal编程技术网

Java 在YAML嵌套数据中搜索值

Java 在YAML嵌套数据中搜索值,java,xpath,jackson,yaml,snakeyaml,Java,Xpath,Jackson,Yaml,Snakeyaml,我目前正试图将YAML文件解析为运行某些测试的输入/配置。问题是:使用Jackson,嵌套数据似乎不适合类,无论我为其设计了什么结构,几乎每次我都会得到这样的结果: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token 我打算使用类似XPath的方法简单地搜索YAML文件

我目前正试图将YAML文件解析为运行某些测试的输入/配置。问题是:使用Jackson,嵌套数据似乎不适合类,无论我为其设计了什么结构,几乎每次我都会得到这样的结果:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token
我打算使用类似XPath的方法简单地搜索YAML文件中的数据,而不必担心映射对象和有限级别的嵌套

下面是示例类:

public class YAMLInput {

    private ArrayList<SomeContainer> containers;
    //getter and setters

    private class SomeContainer {
        private String name; 
        private String path;
        private ArrayList<Integer> intList;
        private ArrayList<String> strList;
        private ArrayList<SomeObject> someObjList;

        private class SomeObject {
             private String objectName;
             private ArrayList<String> strList;
        }

    }
}
其思想是为YAMLInput类构建一个构造函数:


与这个假设的SearchableYAMLData类最接近的可用工具是什么?

您得到的错误可能是由于您显示的YAML与您显示的类不对应。YAML数据中的someObjList是一个包含键值对的映射,第一个键是obj1,而在类中,它是一个ArrayList。这对应于YAML数据中的一个序列,应该如下所示:

someObjList: 
    - objName: strname
      strList: 
         - 100
         - 200
         - 300
    - # (...)
但是,我不确定,因为您没有真正显示产生错误的代码

也就是说,如果您正在寻找通过任意YAML进行搜索的方法,请不要使用Jackson。Jackson是一个反序列化工具,您不想反序列化您的YAML;你只想走它的结构。为此,您可以使用SnakeYAML,这是Jackson使用的YAML解析器:

Yaml yaml = new Yaml();
Node root = yaml.compose(new StringReader("foo: bar"));
根节点可以是ScalarNode、MappingNode或SequenceNode。后两个节点将包含您可以访问的子节点。这种结构对于类似XPath的搜索当然是可行的

如果您追求性能,一种更快的方法是使用SnakeYaml的顺序解析接口。基本上,您可以从解析器中连续查询下一个事件,并检查您正在搜索的路径是否包含它。如果是这样,请继续查询其子元素并在其中的路径中搜索下一个元素。如果没有,则解析并转储当前事件的所有子内容,然后继续搜索当前路径元素


如果您可以阅读Python,您可以从中获得一些灵感,通过事件解析输入YAML,并可以指定要附加数据的路径。

您得到的错误可能源于您显示的YAML与您显示的类不对应。YAML数据中的someObjList是一个包含键值对的映射,第一个键是obj1,而在类中,它是一个ArrayList。这对应于YAML数据中的一个序列,应该如下所示:

someObjList: 
    - objName: strname
      strList: 
         - 100
         - 200
         - 300
    - # (...)
但是,我不确定,因为您没有真正显示产生错误的代码

也就是说,如果您正在寻找通过任意YAML进行搜索的方法,请不要使用Jackson。Jackson是一个反序列化工具,您不想反序列化您的YAML;你只想走它的结构。为此,您可以使用SnakeYAML,这是Jackson使用的YAML解析器:

Yaml yaml = new Yaml();
Node root = yaml.compose(new StringReader("foo: bar"));
根节点可以是ScalarNode、MappingNode或SequenceNode。后两个节点将包含您可以访问的子节点。这种结构对于类似XPath的搜索当然是可行的

如果您追求性能,一种更快的方法是使用SnakeYaml的顺序解析接口。基本上,您可以从解析器中连续查询下一个事件,并检查您正在搜索的路径是否包含它。如果是这样,请继续查询其子元素并在其中的路径中搜索下一个元素。如果没有,则解析并转储当前事件的所有子内容,然后继续搜索当前路径元素

如果您可以阅读Python,您可以从中获得一些灵感,通过事件解析输入YAML,并可以指定要附加数据的路径。

您可以看到,无法反序列化java.util.ArrayList的实例,因为您在根级别定义了ArrayList容器,但YAML文件包含对象。为了避免这种情况,我们需要将ObjectMapper配置为接受单个对象(如数组):

此外,模型中未定义obj1和obj2。因此,您应该删除它们或创建额外的包装器对象。但如果只需要遍历YAML文件,则可以将其作为映射读取。以下代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

import java.io.File;
import java.util.Map;

public class YamlApp {

    public static void main(String[] args) throws Exception {
        File yamlFile = new File("./resource/test.yaml").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        Map yaml = mapper.readValue(yamlFile, Map.class);

        System.out.println(yaml);
    }
}
印刷品:

{container={name=Cont1, path=/storage/outputFolder, intList=[100, 200, 300], strList=[strFirst, strSecond, strThird], someObjList={obj1={objName=strname, strList=[100, 200, 300]}, obj2={objName=strname2, strList=[1002, 2002, 3002]}}}}
您可以看到,无法从START_对象标记反序列化java.util.ArrayList的实例,因为在根级别您定义了ArrayList容器,但YAML文件包含对象。为了避免这种情况,我们需要将ObjectMapper配置为接受单个对象(如数组):

此外,模型中未定义obj1和obj2。因此,您应该删除它们或创建额外的包装器对象。但如果只需要遍历YAML文件,则可以将其作为映射读取。以下代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

import java.io.File;
import java.util.Map;

public class YamlApp {

    public static void main(String[] args) throws Exception {
        File yamlFile = new File("./resource/test.yaml").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        Map yaml = mapper.readValue(yamlFile, Map.class);

        System.out.println(yaml);
    }
}
印刷品:

{container={name=Cont1, path=/storage/outputFolder, intList=[100, 200, 300], strList=[strFirst, strSecond, strThird], someObjList={obj1={objName=strname, strList=[100, 200, 300]}, obj2={objName=strname2, strList=[1002, 2002, 3002]}}}}