7

Let's say I have one file, defaults.yaml:

pool:
  idleConnectionTestPeriodSeconds: 30
  idleMaxAgeInMinutes: 60
  partitionCount: 4
  acquireIncrement: 5
  username: dev
  password: dev_password

and another file, production.yaml:

pool:
  username: prod
  password: prod_password

At runtime, how do I read both files and merge them into one such that the application 'sees' the following?

pool:
  idleConnectionTestPeriodSeconds: 30
  idleMaxAgeInMinutes: 60
  partitionCount: 4
  acquireIncrement: 5
  username: prod
  password: prod_password

Is this possible with, say, SnakeYAML? Any other tools?

I know one option is to read multiple files in as Maps and then merge them myself, render the merge to a single temporary file and then read that, but that's a heavyweight solution. Can an existing tool do this already?

Les Hazlewood
  • 18,480
  • 13
  • 68
  • 76
  • I don't think an existing tool would do anything less 'heavyweight' than what you're thinking of doing - another option would be to skip the temp file and just merge Maps in memory, though. – spirulence Jan 22 '15 at 16:12

1 Answers1

9

You can use Jackson, the key is using ObjectMapper.readerForUpdating() and annotate the field with @JsonMerge (or all the missing fields in next objects will overwrite the old one):

Maven:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.9</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-yaml</artifactId>
        <version>2.9.9</version>
    </dependency>

Code:

public class TestJackson {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        MyConfig myConfig = new MyConfig();
        ObjectReader objectReader = mapper.readerForUpdating(myConfig);
        objectReader.readValue(new File("misc/a.yaml"));
        objectReader.readValue(new File("misc/b.yaml"));
        System.out.println(myConfig);
    }

    @Data
    public static class MyConfig {
        @JsonMerge
        private Pool pool;
    }

    @Data
    public static class Pool {
        private Integer idleConnectionTestPeriodSeconds;
        private Integer idleMaxAgeInMinutes;
        private Integer partitionCount;
        private Integer acquireIncrement;
        private String username;
        private String password;
    }
}
yelliver
  • 5,648
  • 5
  • 34
  • 65