我试图将域(例如OrgUnit)实例作为JSON编组并解组为数据库字段,如下所示:
class OrgUnit{
String name
OrgUnit parent
static hasMany = [children:orgUnit]
}
class History{
String data
}
class OrgUnitService{
History marshal(OrgUnit orgUnit){
return new History([
data : (orgUnit.properties as JSON).toString()
]).save()
}
OrgUnit unmarshal(History history){
return OrgUnit.newInstance( JSON.parse(history.data))
}
}
它适用于像name这样的简单字段,但是像子节点这样的字段在unmarshaled对象中是空的。
history.data字段包含以下子信息:
{"name":"b","children":[{"class":"demo.OrgUnit","id":3,"children":null,"name":"c"}]}
我使用的是Grails 2.2.4。 有什么建议!?
更新 我在Grails 2.4.3上测试过它。它按预期工作。 history.data字段的内容在两个Grails版本中都相同。问题在于解组部分。
答案 0 :(得分:0)
关键部分是 properties map创建域实例。它用于控制器中的默认保存操作。它可能是控制器中的安全问题,但我将其从范围中删除。
在Grails版本2.2.4中,它不会将引用与实例绑定。 解决方法是,手动执行此操作:
class HistoryService {
def grailsApplication
History marshal(OrgUnit orgUnit) {
return new History([
data: (orgUnit.properties as JSON).toString()
]).save(failOnError: true)
}
OrgUnit unmarshal(History history) {
def data = JSON.parse(history.data)
OrgUnit instance = OrgUnit.newInstance(data)
def domainClass = grailsApplication.getDomainClass(OrgUnit.class.name)
domainClass.persistentProperties.each{p->
if (p.oneToMany || p.manyToMany){
def refDataList = data."$p.name"
refDataList.each{refData->
instance."$p.name" << getDomainClass(refData.class).read(refData.id as Long)
}
}else if (p.manyToOne || p.oneToOne){
def refData = data."$p.name"
if(refData && refData.class && refData.id){ // if reference field has value null
instance."$p.name" = getDomainClass(refData.class).read(refData.id as Long)
}
}
}
return instance
}
private def getDomainClass(String domainName){
return grailsApplication.classLoader.loadClass(domainName)
}
}