How does Grails 2.5.6 parse and map request JSON to POGO?

做~自己de王妃 提交于 2019-12-11 15:42:54

问题


Tl;dr: I want to get test MyCmdTest."data bind works" in this code green.
Thanks to Jeff Scott Brown for getting me that far.


I have a POGO with some custom conversions from JSON which I expect to receive in a Grails controller:

def myAction(MyCmd myData) {
    ...
}

With:

@Validateable
class MyCmd {
    SomeType some

    void setSome(Object value) {
        this.some = customMap(value)
    }
}

Note how customMap creates an instance of SomeType from a JSON value (say, a String). Let's assume the default setter won't work; for instance, an pattern we have around more than once is an enum like this:

enum SomeType {
    Foo(17, "foos"),
    Bar(19, "barista")

    int id
    String jsonName

    SomeType(id, jsonName) {
        this.id = id
        this.jsonName = jsonName
    }
}

Here, customMap would take an integer or string, and return the matching case (or null, if none fits).

Now, I have a unit test of the following form:

class RegistrationCmdTest extends Specification {
    String validData // hard-coded, conforms to JSON schema

    void test() {
        MyCmd cmd = new MyCmd(JSON.parse(validData))
        // check members: success

        MyCmd cmd2 = JSON.parse(validData) as MyCmd
        // check members: success
    }
}

Apparently, setSome is called in both variants.

I also have a controller unit test that sets the request JSON to the same string:

void "register successfully"() {
    given:
    ResonseCmd = someMock()

    when:
    controller.request.method = 'POST'
    controller.request.contentType = "application/json"
    controller.request.json = validData
    controller.myAction()

    then:
    noExceptionThrown()
    // successful validations: service called, etc.
}

Basically the same thing also runs as integration test.

However, the mapping fails when running the full application; some == null.

Which methods do I have to implement or override so Grails calls my conversions (here, customMap) instead of inserting null where it doesn't know what to do?


回答1:


It's possible to customize data binding using the @BindUsing annotation:

@BindUsing({ newCmd, jsonMap ->
    customMap(jsonMap['someType'])
})
SomeType someType

See also the MWE repo.

Sources: Hubert Klein Ikkink @ DZone, Official Docs (there are other ways to customize)



来源:https://stackoverflow.com/questions/52988656/how-does-grails-2-5-6-parse-and-map-request-json-to-pogo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!