Grails - 如何让域类将JSON转换为域属性
我想教我的域类自动将JSON.parse(someJSON)的结果转换为也是自定义域类的成员。Grails - 如何让域类将JSON转换为域属性
鉴于这些领域类:
class Person {
Long id
String name
static hasMany = [aliases: PersonAlias]
}
class PersonAlias {
Person person
Long id
String name
}
和代表一些PersonAliases一个人这样JSON:
{
"id":20044397,
"name":"John Smith",
"aliases":[{"id":13376,"name":"Johnny Smith"},{"id":13377,"name":"J. Smith"}]
}
我想保持控制简单,如:
class PersonController {
def saveViaAjax = {
def props = JSON.parse(params.JSON)
Person p = Person.get(props.id)
p.properties = props
p.save(flush: true)
}
}
但可悲的是我得到这个错误:
Failed to convert property value of type 'org.codehaus.groovy.grails.web.json.JSONArray' to required type 'java.util.Set' for property 'aliases'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.codehaus.groovy.grails.web.json.JSONObject] to required type [heavymeta.PersonAlias] for property 'aliases[0]': no matching editors or conversion strategy found
所以,我想教我的领域类如何将JSON数据自动转换为PersonAlias实例。我想避免在将控制器中的数据传递给Domain对象之前格式化数据。我如何实现这些目标?
可以使用bindUsing注解,并提供自定义绑定代码的JSON转换为属性的约束注解。
class Person {
Long id
String name
@BindUsing({obj, source ->
List retVal = []
def aliases = source['aliases']
if(aliases) {
aliases.each {
retVal << new PersonAlias(name:it.name)
}
}
return retVal
})
List<PersonAlias> aliases
static hasMany = [aliases: PersonAlias]
}
我认为这个插件:https://github.com/pedjak/grails-marshallers可能会做你想要的?虽然我没有尝试过。
我喜欢那个插件,但它没有提供我要求的功能。它提供了一种替代方法来利用Grails现有的工具将对象编组为JSON。我需要将JSON转换为我的域类的实例。我有代码要这样做,但我想将其插入到我的域类中,以便它仅作为domainInstance.properties = convertedJSON的副作用发生。 – 2012-08-07 21:52:44
我也遇到这样的问题 - 我尽我所能来记录我的网站上修复 - 见http://dalelotts.com/software-architect/grails
一般的解决方案是将JSON转换为可用于数据绑定的参数图。网站上的更多信息,包括驱动DomainClassMarshaller为JSON
protected Object readFromJson(Class type, InputStream entityStream, String charset) {
def mapper = new ObjectMapper();
def parsedJSON = mapper.readValue(entityStream, typeRef);
Map<String, Object> map = new HashMap<>();
parsedJSON.entrySet().each {Map.Entry<String, Object> entry ->
if (List.isAssignableFrom(entry.getValue().getClass())) {
List values = (List) entry.getValue();
int limit = values.size()
for (int i = 0; i < limit; i++) {
final theValue = values.get(i)
map.put(entry.key + '[' + i + ']', theValue)
appendMapValues(map, theValue, entry.key + '[' + i + ']')
}
} else {
map.put(entry.key, entry.value);
}
}
def result = type.metaClass.invokeConstructor(map)
// Workaround for http://jira.codehaus.org/browse/GRAILS-1984
if (!result.id) {
result.id = idFromMap(map)
}
result
}
private void appendMapValues(Map<String, Object> theMap, Object theValue, String prefix) {
if (Map.isAssignableFrom(theValue.getClass())) {
Map<String, Object> valueMap = (Map<String, Object>) theValue;
for (Map.Entry<String, Object> valueEntry : valueMap.entrySet()) {
theMap.put(prefix + '.' + valueEntry.key, valueEntry.value)
appendMapValues(theMap, valueEntry.value, prefix + '.' + valueEntry.key)
}
}
}
Grails应该已经能够编组JSON。有一个需要在config.groovy中打开的设置。 – cdeszaq 2012-08-07 12:59:49
Grails已经在一定程度上编组了JSON ......在上面的代码中,我找到了一个可行的Person对象,除了成员别名 – 2012-08-07 21:49:32
,您是否找到了针对您的问题的解决方案? – 2013-02-26 06:53:39