How does Grails 2.5.6 parse and map request JSON t

2019-08-23 23:43发布

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条回答
霸刀☆藐视天下
2楼-- · 2019-08-24 00:10

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)

查看更多
登录 后发表回答