我正在使用grailsViews和jsonApi格式进行项目。我正在使用Grails v3.3.9和jsonViews v1.2.10。
因此,视图为从您的域模型生成jsonApi提供了模板支持,但是我找不到允许您根据发布/修补的数据构建域对象(和树)的逆模型。
我设法使这个笨拙的版本起作用,但这是一个快速的技巧。
本质上,我必须重写RestfulController中的createResource方法。这是抓住帖子的正文并对其进行解析。它浸入json并找到属性,并尝试将bindData用于此简单属性映射。
关系更难。我必须遍历这些内容,看看每个标签是否有包含数据的子级。
然后我必须addTo<Tag>
(对于每个条目,如果我可以在域模型中找到要添加到集合的实例。此代码有很多问题-但实际上可以解决持久化新的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团队可能对此有所作为。如果没有,我将请求功能增强。
还有一些命令对象,从技术上讲,您可以将Domain对象用作命令对象。我不建议在玩具应用程序外部将域对象用作命令对象,因为存在固有的安全风险,这就是为什么我认为该对象不是...
但是我建议您使用命令对象,因为它们以某种方式为您提供了基本的验证并记录了您的控制器API。需要注意的是,我通常尝试使命令对象保持明亮状态,而不添加服务或执行调用,原因与您在域中不执行命令,内存消耗和db调用属于过渡服务中的原因相同。同样,我通常将参数从命令对象传递到“漂亮的”布局API,除非命令对象代表Jon文档,否则可能会造成麻烦。
还有一个命令插件,可以像其他Grails工件一样为命令对象提供更多的配置约定。我写的,所以你可以加一点盐:)