yaml文件 轉為 properties —使用java實現


若要轉載本文,請務必聲明出處:https://www.cnblogs.com/zhongyuanzhao000/p/13570432.html


 

最近要用Java實現一個 將yaml文件轉為properties形式的功能,作為一個老搬運工,肯定先查一查有沒有已經開源的代碼啦,[狗頭]!

發現其實有許多在線轉換工具,比如:https://www.toyaml.com/,這是一個在線yaml與properties互轉的工具,效果很不錯,如果只是偶爾進行文件互轉,可以考慮用這個,優點是簡單便捷。

然而,我需要一段Java代碼來實現 yaml轉 properties的功能。。。

發現真有優秀的大佬分享了 yaml轉properties 的java代碼,感謝大佬的分享,詳見:https://www.cnblogs.com/xujingyang/p/10613206.html。簡單地測試了這份代碼,優點是可以實現基本的轉換功能,但是我的需求比較多,還不能滿足要求。所以,基於這份代碼,我進行了功能完善,支持更多的轉換邏輯。

好了,廢話不多說,下面開搞吧!


 

注意,由於借鑒了大佬的源碼,所以下面的代碼大體結構都是相似的。

步驟如下:

1、引入yaml轉properties所需的maven依賴

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
    <version>2.9.4</version>
</dependency>

2、工具類如下:

package com.zzy.utils;

import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;

/**
 * @author zhongyuanzhao000
 * @date 2020/08/27
 */
public class FileTranferUtils {

    /**
     * tranfer yaml file to properties
     * @param path the path of yaml file
     */
    public static void yaml2Prop(String path) {
        List<String> lines = new LinkedList<>();

        // DOT用於隔開key中不同的鍵
        final String DOT = "*";

        //layerOfArray表示當前數組是第幾層數組,默認為0即沒有數組;每遍歷到"["就增加1
        int layerOfArray = 0;

        // inArrays的索引表示yml文件中遍歷到的token位於第幾層數組,而元素內容表示當前遍歷到的token仍在數組內部,元素默認值為false
        boolean[] inArrays = new boolean[4];
        // arrayIndexs的索引表示yml文件中遍歷到的token位於第幾層數組,而元素內容表示其對應的索引,元素默認值為0
        int[] arrayIndexs = new int[4];
        // arrayCuteds的索引表示yml文件中遍歷到的token位於第幾層數組,而元素內容表示 含有中括號的鍵是否已被切去,元素默認值為false
        boolean[] arrayCuteds = new boolean[4];
        // 注意:上面3個數組,目前均初始化了4個元素值,對應0、1、2、3,表示可以解析最多3層數組嵌套;
        // 若要更多層,修改該初始值即可

        try {
            YAMLFactory yamlFactory = new YAMLFactory();
            YAMLParser parser = yamlFactory.createParser(new InputStreamReader(new FileInputStream(path), Charset.forName("utf-8")));

            String key = ""; //這里的key是最終轉換出的properties文件中key,並不是yml文件中的鍵值對中的鍵
            String value = null;
            // 先獲取到基於json格式的第一個token,便於后面的遍歷
            JsonToken token = parser.nextToken();
            while (token != null) {

                // 基於json格式,如果是一個對象開始(即遇到了左花括號"{"時)
                if (JsonToken.START_OBJECT.equals(token)) {
                    // do nothing
                } else if (JsonToken.FIELD_NAME.equals(token)) {   // 基於json格式,如果遇到鍵值對的鍵時

                    // 使用點"."分割每層的key
                    if (key.length() > 0) {
                        // 如果該對象在數組中,並且key包含中括號的數量不等於 當前所在數組的層次時,則添加上數組索引
                        if (inArrays[layerOfArray] == true && containNumbers(key, "[") != layerOfArray) {
                            key = key + "[" + arrayIndexs[layerOfArray] + "]";
                        }
                        key = key + DOT;
                    }
                    key = key + parser.getCurrentName();

                    // 繼續遍歷下一個token
                    token = parser.nextToken();
                    /******************************************************************************************/
                    //如果遇到左中括號"[",表示數組的開始
                    if (JsonToken.START_ARRAY.equals(token)) {
                        // 進入第一層數組
                        layerOfArray++;
                        inArrays[layerOfArray] = true;

                        token = parser.nextToken();
                    }
                    /******************************************************************************************/

                    // 如果遇到子對象的開始(即"{"),則跳入下一個循環
                    if (JsonToken.START_OBJECT.equals(token)) {
                        continue;
                    }

                    /******************************************************************************************/
                    // 此時,當前token遍歷到了一個鍵值對的值時(即到了一個分支盡頭),需要將其放入string數組中
                    value = parser.getText();
                    //如果這個值是單獨被包含在中括號數組內(中括號內沒有鍵值對 對應的鍵),則key肯定還沒有在相應的鍵上添加索引,所以這里要補上索引
                    if (inArrays[layerOfArray] == true && containNumbers(key, "[") != layerOfArray) {
                        key = key + "[" + arrayIndexs[layerOfArray] + "]";
                    }
                    lines.add(key + "=" + value);

                    /******************************************************************************************/
                    // 每當遍歷完一個分支,需要將 key截斷到倒數第二個鍵
                    int dotOffset = key.lastIndexOf(DOT);
                    if (key.length() - 1 == key.lastIndexOf("]")) {
                        arrayCuteds[layerOfArray] = true;
                    }
                    if (dotOffset > 0) {
                        key = key.substring(0, dotOffset);
                    } else {
                        // 若原key中沒有".",則key直接置為""
                        key = "";
                    }


                    // 若截斷后剩下的key的最后一個鍵含有中括號,也就是該鍵的索引即將更新,則去除掉該中括號子串以便於后面添加新的索引
                    if (key.length() > 0 && key.length() - 1 == key.lastIndexOf("]")) {
                        key = key.substring(0, key.lastIndexOf("["));
                    }

                }else if (JsonToken.END_OBJECT.equals(token)) {    // 基於json格式,如果是一個對象結束(即遇到了右花括號"}"時)

                    // 如果當前token在數組內部,則不需要截斷
                    if (inArrays[layerOfArray]) {
                        arrayIndexs[layerOfArray]++;
                    } else {
                        int dotOffset = key.lastIndexOf(DOT);
                        if (dotOffset > 0) {
                            // 若原key中還有".",則截斷到倒數第二個鍵
                            key = key.substring(0, dotOffset);
                        } else {
                            // 若原key中沒有".",則key直接置為""
                            key = "";
                        }
                    }

                } else if (JsonToken.END_ARRAY.equals(token)) {  //如果遇到右中括號"]",表示數組的結束
                    // 若當前層次中 含有中括號的鍵未被切去
                    if (!arrayCuteds[layerOfArray]) {
                        int dotOffset = key.lastIndexOf(DOT);
                        if (dotOffset > 0) {
                            // 若原key中還有".",則截斷到倒數第二個鍵
                            key = key.substring(0, dotOffset);
                        } else {
                            // 若原key中沒有".",則key直接置為""
                            key = "";
                        }
                    }

                    // 重置該層的變量
                    inArrays[layerOfArray] = false;
                    arrayIndexs[layerOfArray] = 0;
                    arrayCuteds[layerOfArray] = false;

                    // 回退到上一層
                    layerOfArray--;

                    // 若截斷后剩下的key的最后一個鍵含有中括號,也就是上一層中 該鍵的索引即將更新,則去除掉該中括號子串 以便於后面添加新的索引
                    if (key.length() > 0 && key.length() - 1 == key.lastIndexOf("]")) {
                        key = key.substring(0, key.lastIndexOf("["));
                    }
                }
                token = parser.nextToken();
            }
            parser.close();

            // 將String字符串數組中的內容打印出來
            for (String line : lines) {
                line = line.replace(DOT, ".");
                System.out.println(line);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 計算 字符串str中包含多少個 模式串s
     * @param str 主字符串
     * @param s 模式串
     * @return
     */
    private static int containNumbers(String str, String s) {
        int count = 0;
        for(int i = 0; i < str.length(); ){
            int c = -1;
            c = str.indexOf(s);
            if (c != -1){
                str = str.substring(c + 1);
                count ++;
            } else {
                break;
            }
        }
        return count;
    }

}

使用yaml2Prop方法,指定yml文件路徑就可以輸出properties內容在控制台上了。

如果需要了解該方法的代碼,建議先參考jackson倉庫,然后將yml文件內容轉為json形式,再根據json形式來理解方法代碼。

最后,如果要檢驗該方法的效果,可以使用在線yaml轉properties工具,然后將工具轉換結果 與 該方法結果比較即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM