问题
I have a class that looks like this:
class Foo {
name
description
static constraints = {
name()
description()
}
}
I want to add display instances of my class in a Flexigrid. When data is sent to a flexigrid it needs to be in a format like JSON or XML... I have chosen JSON. Flexigrid expects JSON arrays it receives to have the following format:
{
"page": "1",
"total": "1",
"rows": [
{
"id": "1",
"cell": [
"1",
"The name of Foo 1",
"The description of Foo 1"
]
},
{
"id": "2",
"cell": [
"2",
"The name of Foo 2",
"The description of Foo 2"
]
}
]
}
To get my Foo
objects into this format I do something similar to this:
def foos = Foo.getAll( 1, 2 )
def results = [:]
results[ "page" ] = params.page
results[ "total" ] = foos.size()
results[ "rows" ] = []
for( foo in foos ) {
def cell = []
cell.add( foo.id )
foo.getProperties().each() { key, value -> // Sometimes get foo.getProperties().each() returns foo.description then foo.name instead of foo.name then foo.description as desired.
cell.add( value.toString() )
}
results[ "rows" ].add( [ "id": foo.id, "cell": cell ] )
}
render results as JSON
The problem is that every once in a while foo.getProperties().each()
returns foo.description
then foo.name
resulting in foo.description
being put in the name column of my flexigrid and foo.name
being put in the description column of my flexigrid for a specific row.
I tried specifying constraints in the Foo
domain class so the getProperties
would return in the correct order, but it didn't work. How can I make sure getProperties
returns properties in a predictable order?
This is how I fixed this issuse:
def items = Foo.getAll()
for( item in items ) {
def cell = []
cell.add( item.id )
Foo.constraints.each() { key, value ->
def itemValue = item.getProperty( key )
if( !( itemValue instanceof Collection ) ) {
cell.add( itemValue.toString() )
}
}
}
So Foo.constraints
gets a map of constraints where each constraint is an instance of Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry
. After testing I have found this map always returns my Foo
static constraints in the order I entered them (also confirmed by Ian). Now only the properties of the item
which are in Foo.constraints
will be added to the cell
for flexigrid.
回答1:
I don't think foo.getProperties()
guarantees anything about the ordering. But Foo.constraints
is overridden at runtime to return not the original closure, but a Map
of ConstrainedProperty
objects and the keys in this map are guaranteed to be in the same order as the constraints closure (this is how scaffolding is able to use the constraints ordering to define the order in which fields are presented in the scaffolded views). So you could do something like
def props = [:] // [:] declares a LinkedHashMap, so order-preserving
Foo.constraints.each { k, v ->
props[k] = foo."${k}"
}
回答2:
foo.getProperties().sort()
or if there's no good way to sort the properties in the order you need, you could always define the order of the properties yourself in a list to iterate over.
def properties = ['name', 'description']
properties.each {
cell.add(foo."$it")
}
来源:https://stackoverflow.com/questions/11150476/grails-getproperties-method-does-not-always-return-properties-in-the-correct-ord