开发者

Using asType with Mixin annotation

开发者 https://www.devze.com 2023-03-29 20:45 出处:网络
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

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号