Grails getProperties 方法并不总是以正确的顺序返回属性



>我有一个看起来像这样的类:

class Foo {
    name
    description
    static constraints = {
        name()
        description()
    }
}

我想在 Flexigrid 中添加我的类的显示实例。 当数据发送到弹性网格时,它需要采用JSON或XML之类的格式。我选择了 JSON。 Flexigrid希望它收到的JSON数组具有以下格式:

{
    "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"
            ]
        }
    ]
}

为了使我的Foo对象采用这种格式,我做了类似的事情:

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

问题是每隔一段时间foo.getProperties().each()返回foo.description然后foo.name导致foo.description被放在我的 flexigrid 的名称列中,foo.name被放在我的 flexigrid 的描述列中特定行。

我尝试在 Foo 域类中指定约束,以便getProperties以正确的顺序返回,但它不起作用。 如何确保getProperties以可预测的顺序返回属性?

这就是我解决这个问题的方式:

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() )
        }
    }
}

因此,Foo.constraints得到了一个约束映射,其中每个约束都是Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry的一个实例。 经过测试,我发现这张地图总是按照我输入的顺序返回我的Foo静态约束(也得到了 Ian 的确认)。 现在,只有Foo.constraints中的item的属性将被添加到 flexigrid 的cell中。

我认为foo.getProperties()不能保证任何关于排序的事情。 但是Foo.constraints在运行时被覆盖,不返回原始闭包,而是Map ConstrainedProperty对象和此映射中的键保证与约束闭包的顺序相同(这就是基架能够使用约束排序来定义字段在基架视图中显示顺序的方式)。 所以你可以做一些类似的事情

def props = [:] // [:] declares a LinkedHashMap, so order-preserving
Foo.constraints.each { k, v ->
  props[k] = foo."${k}"
}

>foo.getProperties().sort()或者如果没有很好的方法按所需的顺序对属性进行排序,则始终可以在列表中自行定义属性的顺序以进行迭代。

def properties = ['name', 'description']
properties.each {
     cell.add(foo."$it")
}

最新更新