Reputation: 509
I have a yaml file that looks like this:
defaultSettings:
a: 1
b: foo
entries:
- name: one
settings:
a: 2
- name: two
settings:
b: bar
- name: three
Assume I have these classes:
class Settings {
public int a;
public String b;
}
class Entry {
public String name;
public Settings settings;
}
class Config {
public Settings defaultSettings;
public List<Entry> entries;
}
The key is that I want to use the defaultSettings
specified at the top of the file for any settings that are not specified in the individual entries. So, the entries would come out as if they had been written like this:
- name: one
settings:
a: 2
b: foo
- name: two
settings:
a: 1
b: bar
- name: three
settings:
a: 1
b: foo
Is there a nice way to do this (e.g., with Jackson, SnakeYAML, etc.)? I have complete control over the code, so I can make modifications if that leads to a nicer way of doing things.
Upvotes: 1
Views: 234
Reputation: 509
I ended up doing this, which works:
class Settings {
public int a;
public String b;
// 0 arg constructor uses the static defaults via the copy constructor
public Settings() {
this(Config.defaultSettings);
}
// copy constructor
public Settings(Settings other) {
// other will be null when creating the default settings
if(other == null) return;
// rest of copy constructor
}
}
class Entry {
public String name;
public Settings settings = Config.defaultSettings; // use default if not set separately
}
class Config {
public static Settings defaultSettings; // this is static
public List<Entry> entries;
// this is a setter that actually sets the static member
public void setDefaultSettings(Settings defaultSettings) {
Config.defaultSettings = defaultSettings);
}
Then with Jackson:
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Configuration config = mapper.readValue(configFile, Config.class);
Essentially, this sets a static Settings
(assuming that defaultSettings
occurs first in the file). In the case where a partial settings block is specified in the yaml, the Settings 0-arg constructor will be used to , which creates a copy of Config.defaultSettings
and then Jackson modifies it with whatever is specified in the file. In the case where no settings
block is in the file for some Entry
, Config.defaultSettings
is used directly (via the field initialization in Entry
). Not too bad, and beats writing a custom deserializer.
I'm still interested if someone has a better way.
Upvotes: 1