Grails supports the concept of dynamic encode/decode methods. A set of standard codecs are bundled with Grails. Grails also supports a simple mechanism for developers to contribute their own codecs that will be recognized at runtime.
Codec Classes
A Grails codec class is a class that may contain an encode closure, a decode closure or both. When a Grails application starts up the Grails framework will dynamically load codecs from the
grails-app/utils/
directory.
The framework will look under
grails-app/utils/
for class names that end with the convention
Codec
. For example one of the standard codecs that ship with Grails is
HTMLCodec
.
If a codec contains an
encode
property assigned a block of code Grails will create a dynamic
encode
method and add that method to the Object class with a name representing the codec that defined the encode closure. For example, the
HTMLCodec
class defines an
encode
block so Grails will attach that closure to the
Object
class with the name
encodeAsHTML
.
The
HTMLCodec
and
URLCodec
classes also define a
decode
block so Grails will attach those with the names
decodeHTML
and
decodeURL
. Dynamic codec methods may be invoked from anywhere in a Grails application. For example, consider a case where a report contains a property called 'description' and that description may contain special characters that need to be escaped to be presented in an HTML document. One way to deal with that in a GSP is to encode the description property using the dynamic encode method as shown below:
${report.description.encodeAsHTML()}
Decoding is performed using
value.decodeHTML()
syntax.
Standard Codecs
HTMLCodecThis codec perfoms HTML escaping and unescaping, so that values you provide can be rendered safely in an HTML page without creating any HTML tags or damaging the page layout. For example, given a value "Don't you know that 2 > 1?" you wouldn't be able to show this safely within an HTML page because the > will look like it closes a tag, which is especially bad if you render this data within an attribute, such as the value attribute of an input field.
Example of usage:
<input name="comment.message" value="${comment.message.encodeAsHTML()}"/>
Note that the HTML encoding does not re-encode apostrophe/single quote so you must use double quotes on attribute values to avoid text with apostrophes messing up your page.
URLCodecURL encoding is required when creating URLs in links or form actions, or any time data may be used to create a URL. It prevents illegal characters getting into the URL to change its meaning, for example a "Apple & Blackberry" is not going to work well as a parameter in a GET request as the ampersand will break the parsing of parameters.
Example of usage:
<a href="/mycontroller/find?searchKey=${lastSearch.encodeAsURL()}">Repeat last search</a>
Base64CodecPerforms Base64 encode/decode functions. Example of usage:
Your registration code is: ${user.registrationCode.encodeAsBase64()}
JavaScriptCodecWill escape Strings so they can be used as valid JavaSctipt strings. Example of usage:
Element.update('${elementId}', '${render(template: "/common/message").encodeAsJavaScript()}')
HexCodecWill encode byte arrays or lists of integers to lowercase hexadecimal strings, and can decode hexadecimal strings into byte arrays. Example of usage:
Selected colour: #${[255,127,255].encodeAsHex()}
MD5CodecWill use the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
Your API Key: ${user.uniqueID.encodeAsMD5()}
MD5BytesCodecWill use the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
byte[] passwordHash = params.password.encodeAsMD5Bytes()
SHA1CodecWill use the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
Your API Key: ${user.uniqueID.encodeAsSHA1()}
SHA1BytesCodecWill use the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
byte[] passwordHash = params.password.encodeAsSHA1Bytes()
SHA256CodecWill use the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:
Your API Key: ${user.uniqueID.encodeAsSHA256()}
SHA256BytesCodecWill use the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:
byte[] passwordHash = params.password.encodeAsSHA256Bytes()
Custom Codecs
Applications may define their own codecs and Grails will load them along with the standard codecs. A custom codec class must be defined in the
grails-app/utils/
directory and the class name must end with
Codec
. The codec may contain a
static
encode
block, a
static
decode
block or both. The block should expect a single argument which will be the object that the dynamic method was invoked on. For Example:
class PigLatinCodec {
static encode = { str ->
// convert the string to piglatin and return the result
}
}
With the above codec in place an application could do something like this:
${lastName.encodeAsPigLatin()}