sourcecode

Yaml의 목록과 Spring Boot의 객체 목록 매핑

codebag 2023. 2. 27. 22:49
반응형

Yaml의 목록과 Spring Boot의 객체 목록 매핑

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 Constructor에서 일반 콩으로 주입하고 있습니다.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]

뭐가 잘못됐는지 단서라도 있나요?

그 이유는 분명 다른 곳에 있을 것이다.설정 없이 개봉 후 Spring Boot 1.2.2만 사용하면 동작합니다.이 레포 좀 봐. 고장낼 수 있어?

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

YAML 파일은 붙여넣은 그대로 표시됩니까?여백, 문자, 특수 문자, 잘못된 표시 같은 건 없나요?검색 경로의 다른 곳에 예상한 파일이 아닌 다른 파일이 있을 수 있습니까?

  • 컨스트럭터는 필요 없습니다.
  • 내부 클래스에 주석을 달 필요가 없습니다.
  • RefreshScope사용할 때 몇 가지 문제가 있다@Configurationgithub 문제를 참조해 주세요.

다음과 같이 클래스를 변경합니다.

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

}

나는 이 기사와 다른 많은 기사들을 참조했지만 도움을 줄 명확한 간결한 답변을 찾을 수 없었다.이 스레드로부터의 참조와 함께 다음과 같이 제 발견을 제안합니다.

스프링 부트 버전: 1.3.5풀어주다

Spring-Core 버전: 4.2.6.풀어주다

의존관계 관리: 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이 기록되었다.이것은 다른 기계에서 개발되었기 때문에 위의 내용을 모두 다시 입력해야 하므로 잘못 입력했다면 양해 바랍니다.

이 통합 코멘트가 많은 사람에게 도움이 되기를 바라며, 이 스레드에 대한 이전 기여자들에게 감사드립니다.

이것도 문제가 많았어요.나는 마침내 무엇이 최종 거래인지 알아냈다.

@Gokhan Oner의 답변을 참조하여 서비스 클래스와 오브젝트를 나타내는POJO를 취득한 후 YAML Configuration Properties 주석을 사용할 경우 오브젝트를 명시적으로 취득해야 합니다.예를 들어 다음과 같습니다.

@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)라고 불러야 한다는 것을.초기화를 기다리고 있었습니다.객체가 그 값으로 만들어지길 바라지만, 그렇지 않았습니다.도움이 되었으면 좋겠다:)

두 가지 방법을 시도해 봤는데 둘 다 효과가 있었어요.

솔루션_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=="}]'

자바

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

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

이 수정은 속성을 주입하려면 @Component가 필요하다고 생각하기 때문에 주입된 클래스를 @ConfigurationPropertites에서 주석을 붙인 클래스에 내부 클래스로 추가하는 것입니다.

언급URL : https://stackoverflow.com/questions/32593014/mapping-list-in-yaml-to-list-of-objects-in-spring-boot

반응형