Skip to content

Commit 8f30985

Browse files
GRAILS-11532 - improve binding JSON to a Map
We were binding a JsonObjectMap to the Map property and that is problematic. This change will turn a JsonObjectMap into a java.util.HashMap before putting it in a DataBindingSource.
1 parent d6ca832 commit 8f30985

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/binding/json/JsonBindingSpec.groovy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package org.codehaus.groovy.grails.web.binding.json
22

33
import grails.artefact.Artefact
44
import grails.test.mixin.TestFor
5+
6+
import org.codehaus.groovy.grails.web.binding.bindingsource.JsonDataBindingSourceCreator.JsonObjectMap
7+
58
import spock.lang.Specification
69

710
@TestFor(BindingController)
@@ -87,6 +90,22 @@ class JsonBindingSpec extends Specification {
8790
model.person instanceof Person
8891
model.person.name == 'Hello öäåÖÄÅ'
8992
}
93+
94+
void 'Test binding JSON to a Map'() {
95+
given:
96+
request.contentType = JSON_CONTENT_TYPE
97+
request.method = 'POST'
98+
request.JSON = '{"mapData": {"name":"Jeff", "country":"USA"}}'
99+
100+
when:
101+
def model = controller.createFamily()
102+
103+
then:
104+
model.family.mapData instanceof Map
105+
!(model.family.mapData instanceof JsonObjectMap)
106+
model.family.mapData.name == 'Jeff'
107+
model.family.mapData.country == 'USA'
108+
}
90109
}
91110

92111
@Artefact('Controller')
@@ -114,4 +133,5 @@ class Person {
114133
class Family {
115134
String lastName
116135
List<Person> familyMembers
136+
Map mapData
117137
}

grails-web/src/main/groovy/org/codehaus/groovy/grails/web/binding/bindingsource/JsonDataBindingSourceCreator.groovy

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,15 @@ class JsonDataBindingSourceCreator extends AbstractRequestBodyDataBindingSourceC
112112
* @return The map
113113
*/
114114
protected Map createJsonObjectMap(JsonElement jsonElement) {
115-
jsonElement instanceof JsonObject ? new JsonObjectMap(jsonElement, gson) : [:]
115+
Map newMap = [:]
116+
if(jsonElement instanceof JsonObject) {
117+
def jom = new JsonObjectMap(jsonElement, gson)
118+
jom.each { k, v ->
119+
def newValue = v instanceof JsonElement ? getValueForJsonElement((JsonElement)v, gson) : v
120+
newMap[k] = newValue
121+
}
122+
}
123+
newMap
116124
}
117125

118126
Object getValueForJsonElement(JsonElement value, Gson gson) {

grails-web/src/test/groovy/org/codehaus/groovy/grails/web/binding/bindingsource/json/JsonDataBindingSourceCreatorSpec.groovy

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.codehaus.groovy.grails.web.binding.bindingsource.json
22

33
import org.codehaus.groovy.grails.web.binding.bindingsource.JsonDataBindingSourceCreator
4+
import org.codehaus.groovy.grails.web.binding.bindingsource.JsonDataBindingSourceCreator.JsonObjectMap
45

56
import spock.lang.Specification
67

@@ -27,17 +28,21 @@ class JsonDataBindingSourceCreatorSpec extends Specification {
2728
bindingSource.containsProperty 'name'
2829
bindingSource['name'] == 'MacBook'
2930
bindingSource['category'] instanceof Map
31+
!(bindingSource['category'] instanceof JsonObjectMap)
3032
bindingSource['category'].size() == 5
3133
bindingSource['category']['name'] == 'laptop'
3234
bindingSource['category']['shouldBeTrue'] == true
3335
bindingSource['category']['shouldBeFalse'] == false
3436
bindingSource['category']['someNumber'].intValue() == 42
3537
bindingSource['category']['shouldBeNull'] == null
36-
bindingSource['languages[0]'] instanceof Map
37-
bindingSource['languages[1]'] instanceof Map
38-
bindingSource['languages[0]']['name'] == 'Groovy'
39-
bindingSource['languages[0]']['company'] == 'GoPivotal'
40-
bindingSource['languages[1]']['name'] == 'Java'
41-
bindingSource['languages[1]']['company'] == 'Oracle'
38+
bindingSource['languages'] instanceof List
39+
bindingSource['languages'][0] instanceof Map
40+
!(bindingSource['languages'][0] instanceof JsonObjectMap)
41+
bindingSource['languages'][1] instanceof Map
42+
!(bindingSource['languages'][1] instanceof JsonObjectMap)
43+
bindingSource['languages'][0]['name'] == 'Groovy'
44+
bindingSource['languages'][0]['company'] == 'GoPivotal'
45+
bindingSource['languages'][1]['name'] == 'Java'
46+
bindingSource['languages'][1]['company'] == 'Oracle'
4247
}
4348
}

0 commit comments

Comments
 (0)