0

I want to parse yaml files with dynamic properties. So, I have yaml files for different countries - netherlands.yml, usa.yml, uk.yml....etc

The content of the files will look like this-

netherlands:
  name: netherlands
  type: country
  location:
    latitude: aaa
    longitude: bbb
  amsterdam:
    name: amsterdam
    type: city
    latitude: xxx
    longitude: yyy
  rotterdam:
    name: rotterdam
    type: city
    latitude: ddd
    longitude: ggg 
  hague:
    name: hague
    type: city
    latitude: kkk
    longitude: lll

I want to parse this and read it this way in my code -

@country(name="netherlands")
Country country;

country.getAmsterdam.getLatitude()

I am using Springboot and Java 11. How to achieve this using annotations? I believe I need to write a custom annotation for each country. But the main issue is the name of the cities will be dynamic for each country and number of cities will also vary from country to country. Also, cities can be added later in the yaml. I was able to write a code to parse the yaml and map it to my object. But what I saw till now is that, it needs to be mapped to a Class with fixed properties, which is not my case. This is the code I wrote but it does not serve my purpose.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
File file = new File(classLoader.getResource("netherlands.yml").getFile());
ObjectMapper om = new ObjectMapper(new YAMLFactory());
Country country = om.readValue(file, Country.class);

    public class Country{    
    private String name ;
    private String type;
    private Location location;    
    // Here I need the dynamic attributes for my cities

   }

I checked many articles but could not find any examples for something like this. Could you please suggest a way to achieve this? Thank you very much for your help.

Haakon Løtveit
  • 1,009
  • 10
  • 18
sana
  • 35
  • 5

1 Answers1

0

In case if your .yml file not going to change in runtime, you might consider using @ConfigurationProperties Spring annotation.

Using it you can create @Configuration class like this:

@Configuration
@Data
public class CountryConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "netherlands")
    private final Country netherlands;
    
    ...
}

You also will need to use additional configs support, described in this answer to allow your netherlands.yml and others be visible for @ConfigurationProperties annotations.

About the dynamic fields generation - it's impossible as Java is a static typed language. And it doesn't have any sense as you will not be able to work with the cities if you don't know the city name. So I suggest you to change the structure of your .yml file to something like:

 netherlands:
  name: netherlands
  type: country
  location:
    latitude: aaa
    longitude: bbb
  cities:
    - amsterdam:
      ....

If it is impossible. When you can consider using private final Map<String, Object> netherlands.

Sergey Vasnev
  • 783
  • 5
  • 18
  • Thanks for your inputs. I do not want to have the cities as a list because while iterating you will need to specify the index, rather I want it to come as a dropdown when you use dot operator on the country name. And that will also address your point how to handle someone not knowing the available cities. It should come as a dropdown, so you can use the getter and setters, like this - `netherlands.getAmsterdam.setLattitude("1234");` I like the Map option. Can you please provide a code sample how to achieve this - `netherlands.getAmsterdam.setLattitude("1234");` – sana Apr 27 '21 at 14:48
  • As i said it's impossible in this way because of language limitations. The best dynamic option for your current schema is a Map netherlands, where you will have keys like "amsterdam". – Sergey Vasnev Apr 27 '21 at 15:07