Spring Boot 3.2中YamlPropertySourceFactory加载特殊字符键丢失问题
问题:Spring Boot加载YAML含特殊字符的键丢失特殊字符
使用Spring Boot 3.2 + Java 21 + SnakeYAML 2.2加载sources.yaml时,发现键"S&P"被加载为"SP",其他含特殊字符的键也存在特殊字符丢失情况。调试发现文件初始加载正确,但后续处理中出现异常。
原因分析
问题出在自定义的YamlPropertySourceFactory中:将YAML内容转换为Properties对象后,再通过PropertiesPropertySource返回。而Properties类基于传统.properties文件格式设计,会自动处理键中的特殊字符(比如&会被视为转义标记或直接忽略),导致原始YAML键中的特殊字符丢失。
解决方案
不要将YAML转换为Properties,而是直接加载YAML为Map,使用MapPropertySource作为属性源,避免Properties对键的特殊处理。
修改后的YamlPropertySourceFactory代码
import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import org.springframework.yaml.snakeyaml.Yaml; import java.io.IOException; import java.util.Map; import java.util.Objects; public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException { Yaml yaml = new Yaml(); Map<String, Object> yamlMap = yaml.load(encodedResource.getResource().getInputStream()); String fileName = encodedResource.getResource().getFilename(); Objects.requireNonNull(fileName); Objects.requireNonNull(yamlMap); return new MapPropertySource(fileName, yamlMap); } }
更简洁的原生方案:Spring Boot内置支持
Spring Boot 3.x支持直接通过@ConfigurationProperties加载外部YAML文件,无需自定义PropertySourceFactory,可简化配置:
- 修改
SourcesConfig2类,移除@PropertySource注解:
@Configuration @EnableConfigurationProperties @ConfigurationProperties(prefix = "sources") @Slf4j public class SourcesConfig2 { @Getter @Setter private Map<String, MetaData> sources; @Data public static class MetaData { private String cron; private boolean calculateCA; private boolean modifyOhlc; private String lastUpdatedTime; private ZoneOffset gmtOffset; } }
- 在
application.properties或application.yaml中指定外部配置文件导入:
spring.config.import=file:config/sources.yml
Spring Boot会直接加载外部sources.yml,并完整保留键中的特殊字符。
验证
修改后重启应用,检查sources映射中的键,"S&P"会被正确保留,不会丢失特殊字符。
内容的提问来源于stack exchange,提问作者ahrooran
相关产品推荐
相关产品推荐

