16.3 Encoding and Decoding Objects - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 3.0.11
16.3 Encoding and Decoding Objects
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 one that may contain an encode closure, a decode closure or both. When a Grails application starts up the Grails framework dynamically loads codecs from thegrails-app/utils/
directory.The framework looks under grails-app/utils/
for class names that end with the convention Codec
. For example one of the standard codecs that ships with Grails is HTMLCodec
.If a codec contains an encode
closure 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
closure, so Grails attaches it with the name encodeAsHTML
.The HTMLCodec
and URLCodec
classes also define a decode
closure, so Grails attaches those with the names decodeHTML
and decodeURL
respectively. 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' which may contain special characters that must 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()}
value.decodeHTML()
syntax.Encoder and Decoder interfaces for staticly compiled code
A preferred way to use codecs is to use the codecLookup bean to get hold ofEncoder
and Decoder
instances .package org.grails.encoder;public interface CodecLookup { public Encoder lookupEncoder(String codecName); public Decoder lookupDecoder(String codecName); }
CodecLookup
and Encoder
interface
import org.grails.encoder.CodecLookupclass CustomTagLib {
CodecLookup codecLookup def myTag = { Map attrs, body ->
out << codecLookup.lookupEncoder('HTML').encode(attrs.something)
}
}
Standard Codecs
HTMLCodecThis codec performs HTML escaping and unescaping, so that values 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 affecting your page.HTMLCodec defaults to HTML4 style escaping (legacy HTMLCodec implementation in Grails versions before 2.3.0) which escapes non-ascii characters.You can use plain XML escaping instead of HTML4 escaping by setting this config property in
application.groovy
:
grails.views.gsp.htmlcodec = 'xml'
<a href="/mycontroller/find?searchKey=${lastSearch.encodeAsURL()}">
Repeat last search
</a>
Your registration code is: ${user.registrationCode.encodeAsBase64()}
Element.update('${elementId}',
'${render(template: "/common/message").encodeAsJavaScript()}')
Selected colour: #${[255,127,255].encodeAsHex()}
Your API Key: ${user.uniqueID.encodeAsMD5()}
byte[] passwordHash = params.password.encodeAsMD5Bytes()
Your API Key: ${user.uniqueID.encodeAsSHA1()}
byte[] passwordHash = params.password.encodeAsSHA1Bytes()
Your API Key: ${user.uniqueID.encodeAsSHA256()}
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 thegrails-app/utils/
directory and the class name must end with Codec
. The codec may contain a static
encode
closure, a static
decode
closure or both. The closure must accept 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 pig latin and return the result } }
${lastName.encodeAsPigLatin()}