Jackson YAML 生成yaml文件去掉双引号

 背景

         项目需要对接Skywalking,使用nacos动态配置Skywalking告警配置alarm-settings.yml, 所以需要用的yaml相关工具, 这里使用Jackson yaml,也就是jackson-dataformat-yaml,版本2.16.6

         使用alarm-settings.yml中的一段进行测试,在项目端生成类似的yaml文件

第一次尝试:全部默认配置

通过查阅资料,很简单,编写后运行

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

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Test5 {
    public static void main(String[] args) {

        Map<String, Object> yaml = new HashMap<>();
        Map<String, Object> rules = new HashMap<>();
        rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
        rules.put("period", 10);
        rules.put("silence-period", 5);
        rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
        yaml.put("rules", rules);

        // 将Java对象写入YAML文件
        try {
            ObjectMapper objectMapper = new ObjectMapper(
                    new YAMLFactory()
            );
            System.out.println("YAML生成。");
            String bbb = objectMapper.writeValueAsString(yaml);
            System.out.println(bbb);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下,

但是出现问题, 

1,开头出现"---"

2,message属性哪里,出现换行

3,字符串带了"",正常.

这肯定不行,还得进行修改,应该有配置的参数

第二次尝试:开启,关闭一些特性

查找相关帖子后,发现可以关闭或开启一些特性, 这些特性是YAMLGenerator.Feature枚举,了解后,进行代码改进,具体如下

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

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Test51 {
    public static void main(String[] args) {

        Map<String, Object> yaml = new HashMap<>();
        Map<String, Object> rules = new HashMap<>();
        rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
        rules.put("period", 10);
        rules.put("silence-period", 5);
        rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
        yaml.put("rules", rules);

        // 将Java对象写入YAML文件
        try {
            ObjectMapper objectMapper = new ObjectMapper(
                    new YAMLFactory()
                            //禁用开头标识---
                            .disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
                            //自动拆分多行
                            .disable(YAMLGenerator.Feature.SPLIT_LINES)
                            //去掉引号
                            .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
            );
            System.out.println("YAML生成。");
            String bbb = objectMapper.writeValueAsString(yaml);
            System.out.println(bbb);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

即:

WRITE_DOC_START_MARKER:禁用文档开头标记,也就是---

SPLIT_LINES:禁用拆分多行

MINIMIZE_QUOTES:开启尽量减少双引号,

运行结果如下:

虽然3问题都改进2个,但是massge那个双引号还是存在, 经过一番查找,没有找到相关的特性开关,这也是网上大部分提供的方法,无奈之下只能debug查看源码看看有没有什么方法,结果还真有,开心,哈哈哈

第三次尝试:重写StringQuotingChecker

通过debug第二尝试代码,发现MINIMIZE_QUOTES特性的配置生效代码在YAMLGenerator.java 579行,writeString方法中,片段如下

第597行判断中,有一句"_quotingChecker.needToQuoteValue(text)"是ture,导致结果添加了双引号,查看里面代码,_quotingChecker的实例是StringQuotingChecker.Default, 继续调试

发现是,"valueHasQuotableChar(value)"这句的结果,继续往下,发现是StringQuotingChecker.valueHasQuotableChar方法的原因,

这里面就很明显,也就是说,字符串中带有诸如特殊字符[]{}这些,判断是字符串,强制添加双引号.

总结下来,避开valueHasQuotableChar(value)即可以得到想要的结果,不判断特殊字符都去掉双引号,最后修改代码如下:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.util.StringQuotingChecker;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Test52 {
    public static void main(String[] args) {

        Map<String, Object> yaml = new HashMap<>();
        Map<String, Object> rules = new HashMap<>();
        rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
        rules.put("period", 10);
        rules.put("silence-period", 5);
        rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
        yaml.put("rules", rules);

        // 将Java对象写入YAML文件
        try {
            ObjectMapper objectMapper = new ObjectMapper(
                    YAMLFactory.builder()
                            .stringQuotingChecker(new StringQuotingChecker() {
                                @Override
                                public boolean needToQuoteName(String name) {
                                    return isReservedKeyword(name) || looksLikeYAMLNumber(name);
                                }

                                @Override
                                public boolean needToQuoteValue(String value) {
//                    return isReservedKeyword(value) || valueHasQuotableChar(value);
                                    return isReservedKeyword(value);
                                }
                            })
                            .build()
                            //禁用开头标识---
                            .disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
                            //自动拆分多行
                            .disable(YAMLGenerator.Feature.SPLIT_LINES)
                            //去掉引号:另外,需要像上面重写StringQuotingChecker,否则会因为Skywalking配置文件中,因为存在"{","}"等特殊字符而还是会包裹双引号
                            .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
            );
            System.out.println("YAML生成。");
            String bbb = objectMapper.writeValueAsString(yaml);
            System.out.println(bbb);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

这会总算完成了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值