I have been tasked with an assignement at work, that needs persistance of client side settings. These settings are represented by a XML-file in the C# version of the framework I am implementing, and it represents objects with an hierarchical structure of up to six levels. Also, the number of objects in the different levels are sometimes arbitrary, like an ArrayList. Object serialization is unfortunately not an option, due to a requirement of being able to edit the file directly. It has been more than implied that I have to implement the persistance of these settings as a .properties-file, but I am having some concerns about if that is a good idea.
As far as I know, a .properties-file can only be used in the same way as a HashMap, with a key-value pairing of only Strings. The representation of complex objects seems only possible with long, complex key strings, representing the whole "path" of every single element, including it's individual index in possibly several lists.
filters.filter3.traces.rule4.add1.value="8"
I have not been able to find any decent ways to persist hierarchical objects in a .properties-file, but I have not been able to find any definite proof that it is not possible, either.
So, is a .properties-file suitable for storing hierarchical settings-objects? Or should I implement my properties as an XML-file or JSON instead?
I would stick with an XML file. Nothing irritates users more than having different formats with different variants of an API framework.
You can use libraries such as Apache XMLBeans to simplify the process of reading and writing to XML files, using schema files to auto-generate appropriate Java classes.
Properties files can be used to store hierarchical data, but it's a real pain to edit that stuff by hand and it's easy to introduce errors. Some would argue that XML editing isn't a breeze either, but at least there exists editors that can make this easier when linked with an XSD.
I have always found this way of storing hierarchical configuration data quite cumbersome, but it is very well possible. For example, it is (used to be?) the most common way of configuring Log4j, but from my experience, more and more developers are switching to XML here as well.
I really fail to see the point of using properties files for this purpose.
You have a perfect example in the form of log4j
: here is property sample from here.
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/bensApps.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
If you have a hierarchy in those keys, like:
Map<String,Object> root = new HashMap<>();
root.put("level1", "foobar");
root.put("level2", Collections.singletonMap("p", "foobar");
It is up to you to translate it into:
level1=foobar
level2.p=foobar
And when reading the file, to split .
into submap:
Map<String, Object> root = new HashMap<>();
Properties propz = new Properties();
// load from your file
for (Map.Entry<String,Object> entry : propz.entrySet()) {
String[] path = entry.getKey().split('\\.');
Map<String,Object> parent = root;
int n = path.length - 1;
for (int i = 0; i < n; ++i) {
String p = path[i];
Object child = parent.get(p);
if (null == child) {
Map<String,Object> _p = new HashMap<>();
parent.put(p, _p);
parent = _p;
} else if (child instanceof Map) {
parent = (Map<String,Objext>) child;
} else {
// it is up to you to do something when the path extends beyond a "final" key
}
}
parent.put(path[n], entry.getValue());
}
However, this is a "reinvent the wheel" pattern, the other answers point you probably better solution than doing it by yourself. This example also show you one kind of problem:
p1=foobar
p1.p2=foobar
In the case of a machine generated properties, this won't happen, and an exception is perhaps the best answer. But in the case of human manipulated properties, this may have some meaning.
On a side note, since Java 7 come with JAXB, you can also do it in full XML, without requiring additional libraries. And using a hierarchy of some sort.
I think you've already got the gist of it - Java properties files can express hierarchies, but awkwardly.
Take a look at the Typesafe Config library, which is what Play Framework uses. Its primary language is HOCON (human-optimized config notation) which is great for expressing hierarchical properties. The library also plays well with both properties files and JSON, so you can easily support any and all of these languages simultaneously.
In a Java properties file, as you've said, you're restricted to only using dotted keys
a.b.c = 42
In HOCON, you can choose to either do that or to nest sections with curly braces. So that example could be expressed in any of the following ways:
a.b.c : 42
a {
b.c : 42
}
a.b {
c : 42
}
a {
b {
c : 42
}
}
来源:https://stackoverflow.com/questions/25970045/is-a-properties-file-suitable-for-storing-hierarchical-settings-objects