【问题标题】:Marshal / unmarshal domain instance to JSON in Grails在 Grails 中将域实例编组/解组为 JSON
【发布时间】:2014-10-23 16:44:56
【问题描述】:

我正在尝试将域(例如 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))
  }
}

它适用于名称等简单字段,但子字段等字段在未编组对象中为空。

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 版本中是相同的。问题在于解组部分。

【问题讨论】:

标签: json grails grails-orm marshalling unmarshalling


【解决方案1】:

关键部分是通过 properties 映射创建域实例。它用于控制器中的默认 save 操作。这可能是控制器中的安全问题,但我将其排除在了范围之外。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    相关资源
    最近更新 更多