在 Yaml 映射列表到 Spring 引导中的对象列表

在我的 Spring Boot 应用程序中,我有一个 application.yaml 配置文件,内容如下。我想把它作为一个 Configuration 对象注入到通道配置列表中:

available-payment-channels-list:
xyz: "123"
channelConfigurations:
-
name: "Company X"
companyBankAccount: "1000200030004000"
-
name: "Company Y"
companyBankAccount: "1000200030004000"

还有@Configuration 对象,我想用 PaymentConfiguration 对象列表填充它:

    @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]

有什么线索吗?

135769 次浏览
  • 你不需要构造函数
  • 您不需要对内部类进行注释
  • @Configuration一起使用时,RefreshScope有一些问题。请参阅 这个 Github 问题

把你的课改成这样:

@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
}


}

原因肯定在别的地方。只使用 SpringBoot1.2.2开箱即用,没有配置,它是 只是工作。看看这个回购,你能把它弄坏吗?

Https://github.com/konrad-garus/so-yaml

您确定 YAML 文件看起来和粘贴的一样吗?没有额外的空格、字符、特殊字符、错误缩进之类的吗?有没有可能您在搜索路径的其他地方使用了另一个文件,而不是您所期望的文件?

这次我也有很多问题,我终于知道最后的交易是什么了。

参考@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。我在等待初始化,希望对象是用值构建的,但是没有。希望对你有所帮助:)

我参考了这篇文章和许多其他文章,没有找到一个明确简洁的回答来帮助。我提供我的发现,从这个帖子的一些参考,在以下:

Spring-Boot 版本: 1.3.5. 发布

Spring-Core 版本: 4.2.6. 发布

依赖管理: Brixton.SR1

以下是雅穆尔的相关摘录:

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。这是在另一台机器上开发的,因此我必须重新输入以上所有,所以请原谅我提前如果我不小心打错了。

我希望这个合并评论对许多人有帮助,我感谢以前的贡献者对这个线程!

对我来说,修复方法是将注入的类作为内部类添加到用@ConfigurationProperites 注释的类中,因为我认为需要@Component 来注入属性。

我尝试了两种解决方案,两种都有效。

解决方案 _ 1

。 yml

available-users-list:
configurations:
-
username: eXvn817zDinHun2QLQ==
password: IP2qP+BQfWKJMVeY7Q==
-
username: uwJlOl/jP6/fZLMm0w==
password: IP2qP+BQKJLIMVeY7Q==


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=="}]'

爪哇咖啡

@Value("${available-users-listt}")
String testList;


ObjectMapper mapper = new ObjectMapper();
LoginInfos.LoginInfo[] array = mapper.readValue(testList, LoginInfos.LoginInfo[].class);