A Clojure(Script) implementation of the BeerXML 1.0 schema with cross-format support using Metosin's spec-tools. The library endeavors to support the data specification across JSON, XML, and EDN, and includes all optional fields in the core BeerXML spec.
A deployed copy of the most recent version of common-beer-format can be found on clojars. To use it, add the following as a dependency in your project.clj file:
The next time you build your application, Leiningen or deps.edn should pull it automatically. Alternatively, you may clone or fork the repository to work with it directly.
Once the library has been added as a dependency to your project, you can begin utilizing the specs and parsers.
To see how the application works, try opening a REPL.
(:require [common-beer-format.core :as cbf]
[common-beer-format.specs.fermentables :as cbf-fermentables])
(def fermentables-file
(slurp "resources/xml/fermentables.xml"))
(cbf/parse-and-coerce-xml fermentables-file ::cbf-fermentables/fermentables-wrapper)
Once the file is read and parsed, the code above will return something like this:
{:fermentables
[{:fermentable
{:amount 2.27
:yield 78.0
:supplier "Fussybrewer Malting"
:color 3.0
:name "Pale Malt (2 row) UK"
:moisture 4.0
:type "Grain"
:notes "All purpose base malt for English styles"
:protein 10.2
:origin "United Kingdom"
:coarse-fine-diff 1.5
:version 1
:max-in-batch 100.0
:diastatic-power 45.0}}
{:fermentable
{:amount 0.91
:yield 70.0
:supplier "Fussybrewer Malting"
:color 2.0
:name "Barley, Flaked"
:moisture 9.0
:type "Grain"
:notes "Adds body to porters and stouts, must be mashed"
:protein 13.2
:origin "United Kingdom"
:coarse-fine-diff 1.5
:version 1
:max-in-batch 20.0
:recommend-mash true
:diastatic-power 0.0}}
{:fermentable
{:amount 0.45
:yield 78.0
:supplier "Fussybrewer Malting"
:color 500.0
:name "Black Barley"
:moisture 5.0
:type "Grain"
:notes "Unmalted roasted barley for stouts, porters"
:coarse-fine-diff 1.5
:diastatic-power 0.0
:protein 13.2
:max-in-batch 10.0}}]}
This library takes data structured to the BeerXML specification and provides a layer of conformance and coercion. This data may be represented as XML, JSON, or EDN and similar helper functions exist for each format.
Specs for the following data types have been provided, as well as several wrappers for container objects:
Since BeerXML was obviously built to XML standards, this data model contains more container objects than either JSON or EDN traditionally. To cleanly interop with Clojure Spec, this required the construction of spec wrappers for forms like the following:
{:fermentables
[{:fermentable ...}
{:fermentable ...}]}
;; as well as
{:fermentable
{:amount 2.27
:yield 78.0
:supplier "Fussybrewer Malting"
:color 3.0
:name "Pale Malt (2 row) UK"
:moisture 4.0
:type "Grain"
:notes "All purpose base malt for English styles"
:protein 10.2
:origin "United Kingdom"
:coarse-fine-diff 1.5
:version 1
:max-in-batch 100.0
:diastatic-power 45.0}}
Therefore, specs named like ::fermentable
and ::fermentables
are used to describe the innermost values- meaning a key-value pair of the data describing a fermentable ingredient or a list of fermentable records.
To coerce and conform the data containing those elements, one would use ::fermentable-wrapper
and ::fermentables-wrapper
.
That allows the clean interop between the internal data structure of clojure.data.xml
, which defines the data samples above, and the utilities provided by spec-tools
.
By default, this library uses the tools provided by org.clojure/data.json
and org.clojure/data.xml
.
This was chosen intentionally for two reasons:
For Clojure-only use cases, several streaming functions have been created in the respective namespaces.
common-beer-format also comes pre-packaged with many of the most common brewing ingredients used.
These can safely be used by consumers of the library for computational brewing; however, several assumptions were necessary in the encoding of data.
In general, the ingredient quantities and stock amounts have been hard-coded to 0 - so be sure to update these fields with the amounts you'd like to brew with or keep on hand.
Other assumptions, such as the physical form of the ingredient, may also need to be updated based on your brewing case.
The assumptions are called out in the functions named build-adjunct
, build-hop
, etc in their respective namespaces.
Finally, each canonical ingredient is intended to exist exactly once within the library, but alternative names may be found in the ingredient's ::notes
.
For example, CTZ hops may also be called Zeus hops.
If we've missed an ingredient you'd like to see in common-beer-format, you can fork the repository and open a pull request or suggest it here.
Copyright © 2020-2021 - Wall Brew Co
This software is provided for free, public use as outlined in the MIT License
Can you improve this documentation? These fine people already did:
Nick Nichols, Nick A. Nichols, nnichols & Nick A NicholsEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close