将 Yaml 中的列表映射到 Spring Boot 中的对象列表
Posted
技术标签:
【中文标题】将 Yaml 中的列表映射到 Spring Boot 中的对象列表【英文标题】:Mapping list in Yaml to list of objects in Spring Boot 【发布时间】:2015-12-12 02:52:59 【问题描述】:在我的 Spring Boot 应用程序中,我有 application.yaml 配置文件,其中包含以下内容。我想将其作为带有通道配置列表的配置对象注入:
available-payment-channels-list:
xyz: "123"
channelConfigurations:
-
name: "Company X"
companyBankAccount: "1000200030004000"
-
name: "Company Y"
companyBankAccount: "1000200030004000"
我想用 PaymentConfiguration 对象列表填充@Configuration 对象:
@ConfigurationProperties(prefix = "available-payment-channels-list")
@Configuration
@RefreshScope
public class AvailableChannelsConfiguration
private String xyz;
private List<ChannelConfiguration> channelConfigurations;
public AvailableChannelsConfiguration(String xyz, List<ChannelConfiguration> channelConfigurations)
this.xyz = xyz;
this.channelConfigurations = channelConfigurations;
public AvailableChannelsConfiguration()
// getters, setters
@ConfigurationProperties(prefix = "available-payment-channels-list.channelConfigurations")
@Configuration
public static class ChannelConfiguration
private String name;
private String companyBankAccount;
public ChannelConfiguration(String name, String companyBankAccount)
this.name = name;
this.companyBankAccount = companyBankAccount;
public ChannelConfiguration()
// getters, setters
我将其作为带有@Autowired 构造函数的普通bean 注入。 xyz 的值已正确填充,但是当 Spring 尝试将 yaml 解析为对象列表时,我得到了
nested exception is java.lang.IllegalStateException:
Cannot convert value of type [java.lang.String] to required type
[io.example.AvailableChannelsConfiguration$ChannelConfiguration]
for property 'channelConfigurations[0]': no matching editors or
conversion strategy found]
有什么线索吗?
【问题讨论】:
我遇到了完全相同的问题:我尝试了很多东西,但我得到了一个空对象,或者同样的错误Cannot convert value of type ... String .... to MyObject ... no matching editors or conversion strategy found
。奇怪的是我没有更改 Spring Boot 中可能影响 SnakeYAML 参数或行为的任何内容......实际上,到底是什么?
我差点忘了,我用的是 Spring Boot 1.2.6
我的猜测是 yaml 中 '-' 字符之后的换行符
【参考方案1】:
您不需要构造函数
您不需要注释内部类
RefreshScope
与@Configuration
一起使用时会出现一些问题。请看this github issue
像这样改变你的班级:
@ConfigurationProperties(prefix = "available-payment-channels-list")
@Configuration
public class AvailableChannelsConfiguration
private String xyz;
private List<ChannelConfiguration> channelConfigurations;
// getters, setters
public static class ChannelConfiguration
private String name;
private String companyBankAccount;
// getters, setters
【讨论】:
同样的东西,通常你的代码只是我的嵌套异常的简化 java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [io.example.available_channels .AvailableChannelsConfiguration$ChannelConfiguration] for property 'channelConfigurations[0]': no matching editors or conversion strategy found] 我运行了代码并查看了所有分配的值。您是否删除了 RefreshScope 注释 Re Gokhan:- Spring Boot 版本。 1.2.2 - 核心版本。 4.1.6 ,所有其他 spring 库都是 4.1.5 或 4.1.6(均取自 Spring Boot) 尝试将 ChannelConfiguration 导出到它自己的类。用组件注释标记它。它还需要所有字段的 setter 和 getter。 我用那个版本检查过【参考方案2】:我尝试了 2 个解决方案,都有效。
解决方案_1
.yml
available-users-list:
configurations:
-
username: eXvn817zDinHun2QLQ==
password: IP2qP+BQfWKJMVeY7Q==
-
username: uwJlOl/jP6/fZLMm0w==
password: IP2qP+BQKJLIMVeY7Q==
LoginInfos.java
@ConfigurationProperties(prefix = "available-users-list")
@Configuration
@Component
@Data
public class LoginInfos
private List<LoginInfo> configurations;
@Data
public static class LoginInfo
private String username;
private String password;
List<LoginInfos.LoginInfo> list = loginInfos.getConfigurations();
解决方案_2
.yml
available-users-list: '["username":"eXvn817zHBVn2QLQ==","password":"IfWKJLIMVeY7Q==", "username":"uwJlOl/g9jP6/0w==","password":"IP2qWKJLIMVeY7Q=="]'
Java
@Value("$available-users-listt")
String testList;
ObjectMapper mapper = new ObjectMapper();
LoginInfos.LoginInfo[] array = mapper.readValue(testList, LoginInfos.LoginInfo[].class);
【讨论】:
【参考方案3】:对我来说,解决方法是将注入的类作为内部类添加到带有 @ConfigurationProperites 注释的类中,因为我认为您需要 @Component 来注入属性。
【讨论】:
【参考方案4】:我参考了这篇文章和许多其他文章,但没有找到一个清晰简洁的回复来提供帮助。我在下面提供了我的发现,并参考了该线程的一些参考资料:
Spring-Boot 版本:1.3.5.RELEASE
Spring-Core 版本:4.2.6.RELEASE
依赖管理:Brixton.SR1
以下是相关的yaml摘录:
tools:
toolList:
-
name: jira
matchUrl: http://someJiraUrl
-
name: bamboo
matchUrl: http://someBambooUrl
我创建了一个 Tools.class:
@Component
@ConfigurationProperties(prefix = "tools")
public class Tools
private List<Tool> toolList = new ArrayList<>();
public Tools()
//empty ctor
public List<Tool> getToolList()
return toolList;
public void setToolList(List<Tool> tools)
this.toolList = tools;
我创建了一个 Tool.class:
@Component
public class Tool
private String name;
private String matchUrl;
public Tool()
//empty ctor
public String getName()
return name;
public void setName(String name)
this.name= name;
public String getMatchUrl()
return matchUrl;
public void setMatchUrl(String matchUrl)
this.matchUrl= matchUrl;
@Override
public String toString()
StringBuffer sb = new StringBuffer();
String ls = System.lineSeparator();
sb.append(ls);
sb.append("name: " + name);
sb.append(ls);
sb.append("matchUrl: " + matchUrl);
sb.append(ls);
我通过@Autowired在另一个类中使用了这个组合
@Component
public class SomeOtherClass
private Logger logger = LoggerFactory.getLogger(SomeOtherClass.class);
@Autowired
private Tools tools;
/* excluded non-related code */
@PostConstruct
private void init()
List<Tool> toolList = tools.getToolList();
if(toolList.size() > 0)
for(Tool t: toolList)
logger.info(t.toString());
else
logger.info("*****----- tool size is zero -----*****");
/* excluded non-related code */
在我的日志中记录了名称和匹配的 url。这是在另一台机器上开发的,因此我不得不重新输入以上所有内容,如果我无意中输入错误,请提前原谅我。
我希望这篇合并评论对许多人有所帮助,我感谢之前对该主题的贡献者!
【讨论】:
Tool类不需要@Component
注解
你真的需要一个只是列表包装器的工具类吗?
这为我解决了,尤其是工具类的空构造函数的提示...
我在两个类上都有一个“@AllArgsConstructor”,这就是导致问题的原因。删除它并将“@NorArgsConstructor”留在那里,它就像一个魅力。仅供参考,我在两个类上也都有带有“@Data”的getter和setter。【参考方案5】:
这个我也有很多问题。我终于知道最后的交易是什么了。
参考@Gokhan Oner 的答案,一旦你有了你的服务类和代表你的对象的 POJO,你的 YAML 配置文件又好又瘦,如果你使用注释 @ConfigurationProperties,你必须明确地获取对象能够使用它。喜欢:
@ConfigurationProperties(prefix = "available-payment-channels-list")
//@Configuration <- you don't specificly need this, instead you're doing something else
public class AvailableChannelsConfiguration
private String xyz;
//initialize arraylist
private List<ChannelConfiguration> channelConfigurations = new ArrayList<>();
public AvailableChannelsConfiguration()
for(ChannelConfiguration current : this.getChannelConfigurations())
System.out.println(current.getName()); //TADAAA
public List<ChannelConfiguration> getChannelConfigurations()
return this.channelConfigurations;
public static class ChannelConfiguration
private String name;
private String companyBankAccount;
然后就可以了。这很简单,但我们必须知道我们必须调用对象 getter。我在初始化时等待,希望使用该值构建对象,但没有。希望对你有帮助:)
【讨论】:
没有配置,如何自动装配这个配置对象? 这是我的问题。如果我在没有初始化列表的情况下添加了一个设置器,也可以工作。【参考方案6】:原因一定是在别的地方。仅使用开箱即用的 Spring Boot 1.2.2,无需配置,Just Works。看看这个 repo - 你能打破它吗?
https://github.com/konrad-garus/so-yaml
您确定 YAML 文件看起来与您粘贴的完全一样吗?没有多余的空格、字符、特殊字符、错误缩进或类似的东西?您是否可能在搜索路径的其他位置使用了另一个文件,而不是您期望的文件?
【讨论】:
我做了同样的事情,并且对于干净的 SpringBoot 项目它可以工作。事实证明,我们为不同环境定制的属性加载行为不正常。 嗨@Konrad Garus,请查看***.com/questions/57409781/…这是一个类似的问题。以上是关于将 Yaml 中的列表映射到 Spring Boot 中的对象列表的主要内容,如果未能解决你的问题,请参考以下文章
spring boot yaml 自定义配置 映射到 java POJO