Java 将 Yaml 中的列表映射到 Spring Boot 中的对象列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32593014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mapping list in Yaml to list of objects in Spring Boot
提问by Tomasz Dziurko
In my Spring Boot app I have application.yaml configuration file with following content. I want to have it injected as a Configuration object with list of channel configurations:
在我的 Spring Boot 应用程序中,我有包含以下内容的 application.yaml 配置文件。我想将它作为带有通道配置列表的 Configuration 对象注入:
available-payment-channels-list:
xyz: "123"
channelConfigurations:
-
name: "Company X"
companyBankAccount: "1000200030004000"
-
name: "Company Y"
companyBankAccount: "1000200030004000"
And @Configuration object I want to be populated with list of PaymentConfiguration objects:
我想用 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
}
}
I am injecting this as a normal bean with @Autowired constructor. Value of xyz is populated correctly, but when Spring tries to parse yaml into list of objects I am getting
我将它作为带有 @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]
Any clues what is wrong here?
任何线索这里出了什么问题?
采纳答案by Konrad Garus
The reason must be somewhere else. Using only Spring Boot 1.2.2 out of the box with no configuration, it Just Works. Have a look at this repo - can you get it to break?
原因一定在别的地方。仅使用 Spring Boot 1.2.2 开箱即用,无需配置,它Just Works。看看这个 repo - 你能把它弄坏吗?
https://github.com/konrad-garus/so-yaml
https://github.com/konrad-garus/so-yaml
Are you sure the YAML file looks exactly the way you pasted? No extra whitespace, characters, special characters, mis-indentation or something of that sort? Is it possible you have another file elsewhere in the search path that is used instead of the one you're expecting?
您确定 YAML 文件看起来与您粘贴的完全一样吗?没有多余的空格、字符、特殊字符、错误缩进或类似的东西?您是否有可能在搜索路径中的其他位置使用另一个文件而不是您期望的文件?
回答by Gokhan Oner
- You don't need constructors
- You don't need to annotate inner classes
RefreshScope
have some problems when using with@Configuration
. Please see this github issue
- 你不需要构造函数
- 你不需要注释内部类
RefreshScope
使用 with 时遇到一些问题@Configuration
。请看这个github问题
Change your class like this:
像这样改变你的班级:
@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
}
}
回答by Alex
I had much issues with this one too. I finally found out what's the final deal.
我也有很多问题。我终于知道最后的交易是什么了。
Referring to @Gokhan Oner answer, once you've got your Service class and the POJO representing your object, your YAML config file nice and lean, if you use the annotation @ConfigurationProperties, you have to explicitly get the object for being able to use it. Like :
参考@Gokhan Oner 的答案,一旦您获得了代表您的对象的 Service 类和 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;
}
}
And then here you go. It's simple as hell, but we have to know that we must call the object getter. I was waiting at initialization, wishing the object was being built with the value but no. Hope it helps :)
然后就到这里了。这很简单,但我们必须知道我们必须调用对象 getter。我在等待初始化,希望对象是用值构建的,但没有。希望能帮助到你 :)
回答by JavaJd
I had referenced this article and many others and did not find a clear cut concise response to help. I am offering my discovery, arrived at with some references from this thread, in the following:
我已经参考了这篇文章和许多其他文章,但没有找到一个清晰简洁的回复来提供帮助。我提供了我的发现,从这个线程中得到了一些参考,如下:
Spring-Boot version: 1.3.5.RELEASE
Spring-Boot 版本:1.3.5.RELEASE
Spring-Core version: 4.2.6.RELEASE
Spring-Core 版本:4.2.6.RELEASE
Dependency Management: Brixton.SR1
依赖管理:Brixton.SR1
The following is the pertinent yaml excerpt:
以下是相关的 yaml 摘录:
tools:
toolList:
-
name: jira
matchUrl: http://someJiraUrl
-
name: bamboo
matchUrl: http://someBambooUrl
I created a Tools.class:
我创建了一个 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;
}
}
I created a Tool.class:
我创建了一个 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);
}
}
I used this combination in another class through @Autowired
我通过@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 */
}
And in my logs the name and matching url's were logged. This was developed on another machine and thus I had to retype all of the above so please forgive me in advance if I inadvertently mistyped.
在我的日志中记录了名称和匹配的 url。这是在另一台机器上开发的,因此我不得不重新输入以上所有内容,所以如果我不小心打错了,请提前原谅我。
I hope this consolidation comment is helpful to many and I thank the previous contributors to this thread!
我希望这个整合评论对很多人有帮助,我感谢这个线程的以前的贡献者!
回答by Bashar Ali Labadi
for me the fix was to add the injected class as inner class in the one annotated with @ConfigurationProperites, because I think you need @Component to inject properties.
对我来说,解决方法是将注入的类作为内部类添加到用@ConfigurationProperites 注释的类中,因为我认为您需要@Component 来注入属性。
回答by Vicky
I tried 2 solutions, both work.
我尝试了两种解决方案,都有效。
Solution_1
解决方案_1
.yml
.yml
available-users-list:
configurations:
-
username: eXvn817zDinHun2QLQ==
password: IP2qP+BQfWKJMVeY7Q==
-
username: uwJlOl/jP6/fZLMm0w==
password: IP2qP+BQKJLIMVeY7Q==
LoginInfos.java
登录信息.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();
Solution_2
解决方案_2
.yml
.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);