亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 YAML 嵌套數據中搜索值

在 YAML 嵌套數據中搜索值

暮色呼如 2022-07-27 09:59:41
我目前正在嘗試將 YAML 文件解析為輸入/配置以運行某些測試。問題是:使用杰克遜,無論我為它設計的結構如何,嵌套數據似乎都不適合這個類,幾乎每次我得到這樣的東西: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;        }    }}Yaml 輸入:container:    name: Cont1    path: /storage/outputFolder    intList:         - 100        - 200        - 300    strList:        - strFirst        - strSecond        - strThird    someObjList:         obj1:           objName: strname          strList:              - 100             - 200             - 300        obj2:          # (...)這個想法是為YAMLInput類構建一個構造函數:public YAMLInput( SearchableYAMLData data) {   for(SearchableYAMLData container : data.getList("container")){      this.containers.add( new SomeContainer());      this.containers.get(0) = container.get("name");      //...   }}最接近這個假設SearchableYAMLData類的可用工具是什么?
查看完整描述

2 回答

?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

您得到的錯誤可能源于您顯示的 YAML 與您顯示的類不對應。someObjList在您的 YAML 數據中是一個映射(包含鍵值對,第一個鍵是obj1),而在您的類中,它是一個ArrayList<SomeObject>. 這對應于您的 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"));

root將是 a ScalarNode、 aMappingNode或 a SequenceNode。后兩個將包含您可以下降的子節點。這種結構對于類似 XPath 的搜索當然是可行的。


如果您追求性能,更快的方法是使用parseSnakeYaml 的順序接口。基本上,您不斷地從解析器中查詢下一個事件并檢查您正在搜索的路徑是否包含它。如果是這樣,繼續查詢它的子元素并在那里搜索路徑中的下一個元素。如果沒有,解析并轉儲當前事件的所有子內容,然后繼續搜索當前路徑元素。


如果您可以閱讀 Python,您可以從我的回答中獲得一些靈感,該回答通過事件解析輸入 YAML,并且您可以指定要附加數據的路徑。


查看完整回答
反對 回復 2022-07-27
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

您會看到Cannot deserialize instance of "java.util.ArrayList" out of START_OBJECT token,因為在您定義的根級別ArrayList<SomeContainer> containers但YAML文件包含object. 為避免這種情況,我們需要配置ObjectMapper為接受單個對象,例如array:


ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

此外,obj1并且obj2未在您的模型中定義。所以你應該刪除它們或創建額外的包裝對象。但如果您只需要遍歷YAML文件,您可以將其讀取為Map. 下面的代碼:


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]}}}}


查看完整回答
反對 回復 2022-07-27
  • 2 回答
  • 0 關注
  • 195 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號