2014-01-07 20 views
0

TL;博士

我需要从LinkedHashMap中的GSP模板将数据发送到一个控制器并保留元素的顺序。的Grails的LinkedHashMap到JSON维持秩序的往返

我假设像JSON这样的结构化数据格式是完成此操作的理想方式,但Grails的JSON转换器不会从LinkedHashMap创建有序的JSON对象。

从GSP发送LinkedHashMap数据结构到控制器的最佳方式是什么,以便我可以保留顺序,但在解析数据时做的工作量最小?

长版

我正在开发一个taglib来呈现表中的搜索结果。

在taglib中,我构造了一个LinkedHashMap,它指定了用户想要为列名显示的数据列和标签。例如:

def tableFields = [firstName: "First Name", lastName: "Surname", unique_id: "Your Whizbang ID"] 

该映射被发送到视图,该视图然后将其发送回控制器以从数据库检索搜索结果。我需要保留元素的顺序(因此使用LinkedHashMap)。

我的第一个想法是将LinkedHashMap转换为JSON字符串,然后通过隐藏的表单元素将其发送给控制器。所以,

import grails.converters.JSON 
//taglib class and other code 
def tableFields = [firstName: "First Name", lastName: "Surname", unique_id: "Your Whizbang ID"] as JSON 

但是,它在HTML中创建了一个像这样的JSON对象。我把它放在隐藏字段的值属性中。

<input type="hidden" name="columns" value="{"firstName": "First Name", "lastName": "Surname", "unique_id": "Your Whizbang ID"}" id="columns"> 

这是JSON对象本身。

{"firstName": "First Name", "lastName": "Surname", "unique_id": "Your Whizbang ID"} 

您可以看到JSON字符串的属性与JSON字符串中的LinkedHashMap的顺序相同。但是,JSON对象实际上并不适用于它们属性的保留顺序。因此,当我的控制器接收到列参数,并且我使用其上的JSON.parse()方法时,它会创建一个普通的ol无序HashMap而不是LinkedHashMap。因此,当我将它们呈现为HTML表格时,我的搜索结果中的列显示顺序错误。

At least one fellow也有类似的问题。在运行JSON.parse()后,添加as LinkedHashMap不会削减它,因为.parse()方法会消除顺序。

丹尼尔·伍兹,他在上述职务响应,指出:

如果它不为你工作Grails的数据绑定的问题,你应该能够覆盖隐含属性setter铸就反对您最喜欢的Map实现。

我认为他的说法,我可以写我自己的解析器,这将兑现JSON元素的顺序(即使它在技术上不应该)。我想我也可以写我自己的转换器,使生成的JSON元素会是这样的:

{[{firstName: "First Name"}, {lastName: "Surname"}, {unique_id "Your Whizbang ID"}]} 

我只是害怕的JSON解析器将如何处理,虽然。我会找回HashMaps列表吗?

同样,我真正的问题是从GSP发送LinkedHashMap数据结构到控制器的最佳方式是什么,以便我可以保持顺序,但是在解析数据方面做的工作量最小?我假设这是JSON,但我很高兴被告知,“为什么不只是...”

回答

0

我现在正在做的是通过当前的JSON对象和我可以迭代的列表。在GSP模板,这看起来像:

<g:hiddenField name="columns" value="${colJson}"/> 
<g:hiddenField name="columnOrder" value="${columns.collect{it.key}}"/> 

其中columns是LinkedHashMap的。

然后,能使那些PARAMS控制器,我这样做:

def columnTitles = params.columnOrder.tokenize(",[] ") 
def unorderedColumns = JSON.parse(params.columns) 
def columns = columnTitles.collectEntries{ [(it): unorderedColumns[it]] } 

不优雅,但它的工作,它需要比乔莱因哈特的建议重构少一点。

2

我认为这个问题是Java/Groovy集合的性质与简单的“它是一个列表或它是一张地图“JSON的本质。如果不进行自定义分析,我会建议将您发送的内容稍稍改变。不要试图将LinkedHashMap的Groovy概念强制转换为Javascriptland,也许可以使用Javascript能够理解的习惯用语,比如地图列表。

,而不是在代码中,:

def tableFields = [firstName: "First Name", lastName: "Surname", unique_id: "Your Whizbang ID"] 

怎么样:

List tableFields = [ 
    [ name: 'firstName', label: 'First Name' ], 
    [ name: 'lastName', label: 'Surname' ], 
    [ name: 'unique_id', label: 'Your Whizbang ID' ], 
] 

这转移你的JSON会保持数据(我认为),你需要同时给JSON的东西它理解(列表):

<input type="hidden" name="columns" id="columns" value="[ 
    { "name": "firstName", "label": "First Name" }, 
    { "name": "lastName", "label": "Surname" }, 
    { "name": "unique_id", "label": "Your Whizbang ID" } 
]" /> 

无论处理这将是一个稍微更深的迭代器,但这是公关从优秀的土地到更简单的类型的冰...

+0

你是对的,这只是野兽的性质。如果将这些数据保存为格式化的JSON对我来说非常重要,那么我可能会采取这种方法。然而,它确实不是 - JSON似乎是将结构化数据从服务器发送到客户端,然后返回到服务器的最佳人选。我有一个解决方法(下面),这是不太优雅。 – jonnybot