Skip to content

Commit e1388fb

Browse files
committed
#9401 JSON converter should maintain order of one-to-many relations
1 parent ff45b56 commit e1388fb

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

grails-plugin-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshaller.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,7 @@
1818
import grails.converters.JSON;
1919
import groovy.lang.GroovyObject;
2020

21-
import java.util.ArrayList;
22-
import java.util.Collection;
23-
import java.util.HashMap;
24-
import java.util.HashSet;
25-
import java.util.List;
26-
import java.util.Map;
27-
import java.util.Set;
28-
import java.util.SortedMap;
29-
import java.util.SortedSet;
30-
import java.util.TreeMap;
31-
import java.util.TreeSet;
21+
import java.util.*;
3222

3323
import org.grails.core.util.ClassPropertyFetcher;
3424
import org.grails.core.artefact.DomainClassArtefactHandler;
@@ -148,10 +138,10 @@ else if (referenceObject instanceof SortedSet) {
148138
referenceObject = new TreeSet((SortedSet) referenceObject);
149139
}
150140
else if (referenceObject instanceof Set) {
151-
referenceObject = new HashSet((Set) referenceObject);
141+
referenceObject = new LinkedHashSet((Set) referenceObject);
152142
}
153143
else if (referenceObject instanceof Map) {
154-
referenceObject = new HashMap((Map) referenceObject);
144+
referenceObject = new LinkedHashMap((Map) referenceObject);
155145
}
156146
else if (referenceObject instanceof Collection) {
157147
referenceObject = new ArrayList((Collection) referenceObject);

grails-plugin-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DomainClassMarshaller.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ else if (referenceObject instanceof SortedSet) {
118118
referenceObject = new TreeSet((SortedSet) referenceObject);
119119
}
120120
else if (referenceObject instanceof Set) {
121-
referenceObject = new HashSet((Set) referenceObject);
121+
referenceObject = new LinkedHashSet((Set) referenceObject);
122122
}
123123
else if (referenceObject instanceof Map) {
124-
referenceObject = new HashMap((Map) referenceObject);
124+
referenceObject = new LinkedHashMap((Map) referenceObject);
125125
}
126126
else if (referenceObject instanceof Collection) {
127127
referenceObject = new ArrayList((Collection) referenceObject);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.grails.web.converters.marshaller.json
2+
3+
import grails.converters.JSON
4+
import grails.converters.XML
5+
import grails.core.DefaultGrailsApplication
6+
import grails.persistence.Entity
7+
import org.grails.web.converters.configuration.ConvertersConfigurationInitializer
8+
import spock.lang.Specification
9+
10+
class DomainClassMarshallerSpec extends Specification {
11+
void setup() {
12+
final initializer = new ConvertersConfigurationInitializer()
13+
def grailsApplication = new DefaultGrailsApplication(Author, Book)
14+
grailsApplication.initialise()
15+
initializer.grailsApplication = grailsApplication
16+
initializer.initialize()
17+
}
18+
19+
void "Test DomainClassMarshaller's should maintain order of relations"() {
20+
def json, xml
21+
22+
when:
23+
def book = new Book(
24+
id: 1, version: 2,
25+
authorsSet: authors as Set,
26+
authorsMap: authors.inject([:]) { acc, val ->
27+
acc[val.name] = val
28+
acc
29+
}
30+
)
31+
JSON.use('deep') {
32+
json = book as JSON
33+
}
34+
XML.use('deep') {
35+
xml = book as XML
36+
}
37+
38+
then:
39+
json.toString() == expectedJson
40+
xml.toString() == expectedXml
41+
42+
where:
43+
authors | expectedJson | expectedXml
44+
[new Author(id: 1, name: 'a'), new Author(id: 2, name: 'b')] | '{"id":1,"authorsMap":{"a":{"id":1,"name":"a"},"b":{"id":2,"name":"b"}},"authorsSet":[{"id":1,"name":"a"},{"id":2,"name":"b"}]}' | '<?xml version="1.0" encoding="UTF-8"?><book id="1"><authorsMap><entry key="a" id="1"><name>a</name></entry><entry key="b" id="2"><name>b</name></entry></authorsMap><authorsSet><author id="1"><name>a</name></author><author id="2"><name>b</name></author></authorsSet></book>'
45+
[new Author(id: 2, name: 'b'), new Author(id: 1, name: 'a')] | '{"id":1,"authorsMap":{"b":{"id":2,"name":"b"},"a":{"id":1,"name":"a"}},"authorsSet":[{"id":2,"name":"b"},{"id":1,"name":"a"}]}' | '<?xml version="1.0" encoding="UTF-8"?><book id="1"><authorsMap><entry key="b" id="2"><name>b</name></entry><entry key="a" id="1"><name>a</name></entry></authorsMap><authorsSet><author id="2"><name>b</name></author><author id="1"><name>a</name></author></authorsSet></book>'
46+
}
47+
}
48+
49+
@Entity
50+
class Author {
51+
Long id
52+
Long version
53+
String name
54+
}
55+
56+
@Entity
57+
class Book {
58+
static hasMany = [authorsSet: Author, authorsMap: Author]
59+
Long id
60+
Long version
61+
Set authorsSet
62+
Map authorsMap
63+
}

0 commit comments

Comments
 (0)