If you spend enough time writing Processing sketches you eventually want a way to store and load configuration data.
Chances are good that you've rolled your own. (Chances are also good that if you were familiar with the Java Properties
class you would never consider it even though you basically get that "for free" since Processing is Java.)
I've rolled my own. Two, actually. The first read a text file and looked for name: value
lines, populating a HashMap
. It had some accessor methods (e.g. getIntValue
) to handle casting for you. It worked good enough.
Recently, while working on some a Neurogami MIDI project, I wanted a way to track a list of MIDI devices. My config code was no good for this. I thought about hacking in some way to define a list in a single line of text but it felt icky.
I thought that using YAML or JSON would be a better fit for structured text and lo! Processing supports JSON out of the box.
The code is pretty basic; it's a wrapper around JSONObject
. A has-a
, not an is-a
.
It loads a JSON file (of course) and creates an internal JSONObject
. It has the assorted get<Type>
methods to pull stuff out of that JSONObject
but also has array versions of these as well.
If your JSON file defines an array then to reference it through the JSONObject
you need to use getJSONArray
. For any item in that array you need to use the appropriate get<Type>
method.
This can be a drag. Based on my own experience, a list of items in a config file are almost always going to be of the same type. In my initial use case this was a list of names for MIDI devices. Rather than have to manually grab each string
item I want to just call getStrings
and get a normal String
array.
I'm honestly not sure when I would ever need getBooleans
but I added it for completeness.
So far so good. I can store structured config data. Writing JSON is little more overhead than writing YAML (and both are more work compared to just name:value
, i.e. idiot YAML), but Processing doesn't have a built-in YAML class.
As I write this I'm pondering omitting the top-level braces. This way I could write this:
"devices": ["QuNexus", "01 Internal MIDI"]
... instead of this:
{ "devices": ["QuNexus", "01 Internal MIDI"] }
Having to quote the key names is a drag, too.
I think I want idiot JSON.
Plausibly the Config
constructor could read in the config file and check for a leading brace. If found then assume this is a proper, valid, JSON file. If there is no leading brace then assume this is idiot JSON: A series of name:<JSON thing>
lines. Then each line is split on the first colon character, with the stuff after the colon parsed as JSON.
Or, the file could be reconstructed as proper JSON file by automagically quoting the keys and wrapping it all in braces, and continuing on as if it were given JSON in the first place. This would allow for using the # Some comment
stuff as I had in my original config code.
Worth the effort?
This will require some more thought.
In the meantime, I put the current code up as a gist until I think of a better home for these kinds of short P5 helper classes.
So, in a fit of "How hard could it be?", I took a stab at allowing the use of idiot JSON.
The code is another gist: Configgy.pde
In this version the code looks at the first character of the first line of a config file (after remvoving any blank or comment lines).
If the very first character is a "{" then the whole file is assumed to be proper JSON. Otherwise each line is processed as "idiot JSON", where it is assumed you have a non-quoted key name, then a ":", then valid JSON. All those lines get wrapped up in braces and then parsed as JSON.
Already I can think of more handy features to add ...