Using asType with Mixin annotation
I'd like write a custom type conversion Category in Groovy. The goal is to assign the values of a Map
to the fields of a Groovy bean. In the future there will be different response types. The values of of the Map
are always of type String
but will have to be converted into a different data type. To make this work I created a Category class that implements a method named asType
. This is a simplified example of my code:
class MapCategory {
static Object asType(Map self, Class clazz) {
if(clazz == Response) {
Response response = new Response()
self.each { key, value ->
response.setProperty(key, value)
}
return response
}
DefaultGroovyMethods.asType(self, clazz)
}
}
class Response {
String result
String message
}
This works just fine when when I apply the category using the use
keyword.
use(MapCategory) {
println [result: 'OK', message: 'Success'] as Response
}
However, when I try to use the @Mixin
annotation instead it doesn't seem to work correctly. I get the correct response type but开发者_开发技巧 all fields are null
.
@Mixin(MapCategory)
class MyClass {
def printResponse() {
println [result: 'OK', message: 'Success'] as Response
}
}
Does anybody know why it doesn't work correctly using the annotation?
Mixins don't work that way. You are trying to mix in the method for Map
into your MyClass
object. The mixin would only work if MyClass
extended Map
.
Instead, you want to use the use
keyword like normal, and just use your category as a category.
Alternatively, you might not need it at all. Did you know that you can, by default, convert any map into any GroovyBean without extra code? Just use the map-based constructor, like so:
@groovy.transform.Canonical // Groovy 1.8, just added for automatic toString method
class Response {
String result
String message
}
println new Response([result: 'OK', message: 'Success'])
println([result: 'bad', message: 'blah'] as Response)
Notice, automatic Map conversion works both ways. It's a built-in feature of Groovy.
Of course, if you need something more complex than just assigning bean properties, this won't help.
Note: I'd give you a link, but the Groovy website appears to be broken, and I can't find code examples. :-(
EDIT: Another Suggestion
Instead of using a Category at all, why don't you let the bean itself handle it:
@groovy.transform.Canonical
class Response {
String result
String message
int num
public void setNum(String num) {
this.num = Integer.parseInt(num)
}
}
def map = [result: 'OK', message: 'Success', num: '35' ]
println map as Response
精彩评论