Over a million developers have joined DZone.

Convert java.util.Properties to a Clojure Map

DZone's Guide to

Convert java.util.Properties to a Clojure Map

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

As I previously mentioned, a lot of the work I do involves Clojure & Java interop. This work includes the occasional case of working with a java.util.Properties object from within Clojure. Working with a Properties object isn't a huge deal, but while in Clojure I prefer to use destructuring and the various functions (e.g. update-in, assoc, dissoc, etc) that are designed to work with Clojure maps.

The following example shows how easy it is to convert a Properties object to a Clojure map.

user=> (def prop-obj (doto (java.util.Properties.) (.putAll {"a" 1 "b" 2})))
user=> prop-obj
#<Properties {b=2, a=1}>

user=> (reduce (fn [x [y z]] (assoc x y z)) {} prop-obj)
{"a" 1, "b" 2}
That's fairly easy, but you'll quickly want your keys to be keywords if you plan on destructuring. You can drop in a quick call to keyword to convert the keys; however, you'll probably also want to dasherize the keys to allow for easy destructuring using keys and idiomatic names.
user=> (defn dash-match [[ _ g1 g2]]      
          (str g1 "-" g2))

user=> (defn dasherize [k]
          (-> k
            (clojure.string/replace #"([A-Z]+)([A-Z][a-z])" dash-match)
            (clojure.string/replace #"([a-z\d])([A-Z])" dash-match)

user=> (def prop-obj (doto (java.util.Properties.) (.putAll {"FirstName" "Mike" "LastName" "Green"})))
user=> (reduce (fn [x [y z]] (assoc x y z)) {} prop-obj)                                              
{"LastName" "Green", "FirstName" "Mike"}
user=> (reduce (fn [x [y z]] (assoc x (-> y dasherize keyword) z)) {} prop-obj)
{:last-name "Green", :first-name "Mike"}
That looks good, but you might also find yourself working with a properties file that uses dots or dashes to group similar data. For example, you might find the following entry in your properties file (and the resulting Properties object).
person.name=Mike Green
Loading this into a map works fine; however, it would be nice if the resulting map was nested (to keep common data together, and for easier access using get-in, update-in, etc).

The following code splits on dots and nests the values appropriately.
user=> (def prop-obj (doto (java.util.Properties.) (.putAll {"person.name" "Mike Green" "person.age" "26" "person.sex" "male"})))        
user=> prop-obj                                                                                                                  
#<Properties {person.name=Mike Green, person.age=26, person.sex=male}>
user=> (reduce (fn [x [y z]] (assoc-in x (-> y dasherize (clojure.string/split #"\.")) z)) {} prop-obj)
{"person" {"sex" "male", "age" "26", "name" "Mike Green"}}

user=> (-> (reduce (fn [x [y z]] (assoc-in x (-> y dasherize (clojure.string/split #"\.")) z)) {} prop-obj) clojure.walk/keywordize-keys)
{:person {:sex "male", :age "26", :name "Mike Green"}}
So, not too complicated, but much more complicated than what we started with. It turns out you'll likely want to do other things like parse integers, parse booleans, require keys, and add defaults when a key=value pair isn't specified.

We could go through the effort here of providing all that functionality, but instead I've created a small library that provides all of the above mentioned features: propertea

If you'd like to see the implementation of the above features, you'll just need to look in propertea.core. If you want examples of all of the features of propertea, checkout the tests in github.


From http://blog.jayfields.com/2011/12/convert-javautilproperties-to-clojure.html

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}