在Grails 2.3.5中编组为XML时,我希望从XML中排除null属性。
目前这样的代码
if ( myObj.someProp == null ) log.info("yeap, it's null")
render myObj as XML
将向日志输出“yeap,它为null”,然后呈现看起来像
的XML<myObj>
<someProp />
</myObj>
但我想要的是
<myObj>
</myObj>
或者简单地说(如果没有其他属性)
<myObj />
是否可以将Grails配置为从编组中排除空属性?
另外,使用
def xml = myObj as XML
if ( myObj.someProp == null ) {
xml.excludes = ["someProp"]
}
render xml
不会在所有情况下都有效,因为有时它是results
的列表,其中列表中的项可能具有空属性。
更新
我通过将以下代码添加到BootStrap.groovy
来尝试@ dmahapatro的建议
XML.registerObjectMarshaller(MyObj) {
it.properties.findAll { it.value != null }
}
使用适当的import语句。
结果是不正确的XML:
<myObj>
<entry key="someProp">non-null value</entry>
</myObj>
现在属性不再是标签的名称。相反,使用通用的“entry”标记,因为Grails看到的是Map而不是域对象。
答案 0 :(得分:1)
您可以使用registerObjectMarshaller
修改该行为。
//Bootstrap.groovy
import grails.converters.XML
import my.package.MyObj
XML.registerObjectMarshaller(MyObj) {
it.properties.findAll { it.value != null }
}
<强>更新强>
为了避免由于域类的映射表示而导致的入口标记,可以很容易地转换对象编组器以获得预期结果,如下所示:
XML.registerObjectMarshaller(Author) {obj, xml ->
xml.attribute 'id', "$obj.id"
xml.build {
obj.properties.each {
if(it.value != null) {
"$it.key" it.value
}
}
}
}
答案 1 :(得分:1)
使用内置转换器和marshallers无法从输出中排除空值的标签。阅读了Grails源代码后,有两个相关的类可以控制这种行为,这两个类都不能配置为表现不同。
第一个是DomainClassMarshaller
中的编组类grails-plugin-converters/src/main/groovy/org/codehaus/groovy/grails/web/converters/marshaller/xml/
,相关的行是
xml.startNode(propertyName);
if (!property.isAssociation()) {
// Write non-relation property
Object val = beanWrapper.getPropertyValue(propertyName);
xml.convertAnother(val);
}
这将启动属性的节点(无论其值如何),然后对值调用xml.convertAnother
。
第二个相关的代码行是convertAnother
XML.java
中的grails-plugin-converters/src/main/groovy/grails
方法
if (o == null) {
// noop
}
如果值为null(保留标记为空)并且不引用任何配置选项以使其行为不同,则不执行任何操作。
因此,获得所需行为的唯一方法是从头开始实现它,并将自定义编组器/转换器注册为@dmahapatro建议。
由于OP询问如何使用Grails XML Marshaller执行此操作,因此正确的答案很简单:无法完成。