0

In a Grails 2.5.X app, I can directly bind request data to a command object field of type Map like so:

class MyController {
  def myAction(Command command) {
    Map requestData = command.data
  }
}

class Command {
  Map data
}

It seems that internally Grails uses Gson for the parsing of the JSON data. If for example, the request data is {"page": 6} the corresponding Map will be

[page: new LazilyParsedNumber(6)]

i.e. the value stored in the Map is an instance of com.google.gson.internal.LazilyParsedNumber.

This is problematic for me. I would prefer if the Map were equivalent to that which would be created by:

new groovy.json.JsonSlurper().parseText('{"page": 6}')

which is:

[page: new Integer(6)]

I've looked into the various options for customising the databinding, and none of them hook into the pipeline sufficiently early. In other words, no matter which of the options I choose, the request data has already been processed by Gson.

Is it possible to replace Gson with JsonSlurper as the default parser of JSON request data?

Dónal
  • 185,044
  • 174
  • 569
  • 824

1 Answers1

2

Is it possible to replace Gson with JsonSlurper as the default parser of JSON request data?

Yes, but it isn't something that we document or provide any particular support hooks for.

The default JSON data binding source creator is at https://github.com/grails/grails-core/blob/v2.5.6/grails-web-databinding/src/main/groovy/org/codehaus/groovy/grails/web/binding/bindingsource/JsonDataBindingSourceCreator.groovy.

An instance of that class is added to the Spring application context by the data binding plugin at https://github.com/grails/grails-core/blob/bd7cc10e17d34f20cedce979724f0e3bacd4cdb4/grails-plugin-databinding/src/main/groovy/org/codehaus/groovy/grails/plugins/databinding/DataBindingGrailsPlugin.groovy#L97.

One thing you could do is write your own class which extends AbstractRequestBodyDataBindingSourceCreator (or just implements DataBindingSourceCreator) and register an instance of that class as a bean named jsonDataBindingSourceCreator and that will replace the default one with yours. Then you are on your own to use whatever techniques you like for parsing the body of the request and creating a Map.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • jeff, sorry to ask here but do you happen to know the answer to this question? https://stackoverflow.com/questions/61876296/grails-3-binding-multiple-command-objects-via-post/71247913#71247913 – David Ha Feb 24 '22 at 06:26
  • @DavidHa I posted an answer there. The person who posted the question responded to say that the solution I provided didn't work, the code seems to work and I was not able to understand the comments so I deleted my answer. He asked me to undelete my answer and edit it to include something that he is doing that is different, but that isn't my answer so I don't think that is right, so I left it deleted. – Jeff Scott Brown Feb 24 '22 at 12:52