GrailsView解析jsonApi发布数据-Grails团队中有人在jsonViews中做通用解决方案吗?

时间:2019-01-24 23:15:04

标签: rest grails controller json-api

grails v3.3.9 / jsonViews v1.2.10

使用grailsViews和jsonApi格式处理迷你项目。

因此,视图提供了从域模型生成jsonApi的模板支持,但是我找不到允许您根据发布/修补的数据构建域对象(和树)的逆函数。

我设法使这个笨拙的版本能够正常工作,但是在我上床睡觉之前是一个黑客。

从本质上讲,我不得不重写RestfulController中的createResource方法。这是抓住帖子的正文并对其进行解析。

它浸入json并找到属性,并尝试将bindData用于此简单属性映射。

关系更加困难。我必须遍历这些,看看是否有每个子代都有数据。

然后我必须addTo(如果可以在域模型中找到要添加到集合的实例,则需要为每个条目添加。对于此代码,问题丢失了-但实际上确实可以持久保存新的OrgRoleInstance

//works - needs lots of improvement !! overwites, lookups etc
@Override
protected <T extends OrgRoleInstance> T createResource() {
    def instance = super.resource.newInstance()
    RequestFacade requestFacade = getObjectToBind()
    BufferedReader bodyReader = requestFacade.request.getReader()
    long bodyLength = requestFacade.request.getContentLengthLong()

    String jsonBody = bodyReader.text
    //String strippedBackJson = jsonBody.replaceAll("\\s+","")
    JsonSlurper slurper = new JsonSlurper()
    def body = slurper.parseText (jsonBody)
    def data = body.data
    String bodyDataType = body.data.type
    //json views  api seems to show the class starting in lower case - change to uppercase
    String dataType = convertFirstCharToUppercase (bodyDataType)
    Map attributes = body.data.attributes
    Map relationships = body.data.relationships

    //wrap in a try block
    //def jsonClassRef = Class.forName(toToBindString) - https://stackoverflow.com/questions/13215403/finding-a-class-reflectively-by-its-simple-name-alone
    //assume users know what they are doing ! - just sanity check simple name
    String resClassSimpleName = resource.getSimpleName()
    assert dataType == resClassSimpleName



    //needs a custom bindData
    bindData instance, attributes //getObjectToBind()
    //process any relationships and bind these
    relationships.each {tag, value ->
        def dataArray = value.data
        for (item in dataArray) {
            def jsonType = item['type']
            //convert first char to uppercase
            String type = convertFirstCharToUppercase (jsonType)
            def id = Long.parseLong (item['id'])

            //with type and id try and find in existing domain model
            def refEntity
            Class<?> domainClass = domainClassLookupByName (type)
            if (domainClass) {
                refEntity = domainClass.get (id)
            }
            //help cant overwrite foreign key - clone the mag?
            if (refEntity) {
                def prop = convertFirstCharToUppercase(tag)
                instance."addTo$prop" (refEntity)
                //if (refEntity.validate())
                    //refEntity.save (failOnError:true)
            }
            instance

        }

    }

    //bindData instance, relationships //getObjectToBind()
    instance
}

帖子数据看起来像这样(我很漂亮地将get操作的输出打印到了另一个编辑过的记录末端。

请注意,这是一个缺陷-但是类型的jsonapi呈现:对类型使用小写字符,而不是您期望的大写字母-我必须对此进行补偿)

我希望grails团队可能对此有所作为。

否则,我将尝试请求功能增强

1 个答案:

答案 0 :(得分:0)

有一些命令对象,从技术上讲,您可以将Domain对象用作命令对象。我不建议将域对象用作玩具应用程序之外的命令对象,因为存在固有的安全风险,这就是为什么我认为域对象不是...

但是我建议您使用命令对象,因为它们以某种方式为您提供了基本的验证并记录了您的控制器API。需要注意的是,我通常尝试使命令对象保持明亮状态,而不添加服务或执行调用,原因与您在域中不执行命令,内存消耗和db调用属于过渡服务中的原因相同。同样,我通常将参数从命令对象传递到“巧妙地”布局的API,除非命令对象代表Jon文档,否则可能会造成麻烦。

还有一个命令插件,可以像其他Grails工件一样为命令对象提供更多的配置约定。我写的,所以可以带一点盐:)