Ответ 1
Если вы хотите постоянно включать только определенные свойства, вы действительно хотите использовать интерфейс ObjectMarshaller. Подробнее см. в этой статье.
Я использую grails-1.3.2 и hbase-0.2.4.
У меня есть следующий класс домена:
class MyClass{
String val1
String val2
String val3
//----
}
class MyClassController{
def someAction = {
def myClass = new MyClass()
//----
String valAsJson = (myClass as JSON)
render valAsJson
}
}
Мой вопрос в том, что любой короткий способ отображает только часть свойств (например, выводит все, кроме свойства val3)?
Если вы хотите постоянно включать только определенные свойства, вы действительно хотите использовать интерфейс ObjectMarshaller. Подробнее см. в этой статье.
Вы можете сделать что-то вроде этого:
def myClass = MyClass.get(1)
//include
render myClass.part(include:['val1', 'val2']) as JSON
//except
render job.part(except:['val2','val3']) as JSON
Bootstrap.groovy:
import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events
class BootStrap {
def grailsApplication
def excludedProps = [Events.ONLOAD_EVENT,
Events.BEFORE_DELETE_EVENT, Events.AFTER_DELETE_EVENT,
Events.BEFORE_INSERT_EVENT, Events.AFTER_INSERT_EVENT,
Events.BEFORE_UPDATE_EVENT, Events.AFTER_UPDATE_EVENT]
def init = { servletContext ->
grailsApplication.domainClasses.each{ domainClass ->
domainClass.metaClass.part= { m ->
def map= [:]
if(m.'include'){
m.'include'.each{
map[it]= delegate."${it}"
}
}else if(m.'except'){
m.'except'.addAll excludedProps
def props= domainClass.persistentProperties.findAll {
!(it.name in m.'except')
}
props.each{
map[it.name]= delegate."${it.name}"
}
}
return map
}
}
}
def destroy = {
}
}
Если вы знаете, как создать собственный плагин, просто создайте для него один плагин, чтобы вы могли использовать его во всех приложениях grails.
Или вы могли бы просто создать карту желаемых свойств, а затем закодировать их как JSON
Map m = [ 'val1', 'val2' ].inject( [:] ) { map, val -> map."$val" = a."$val" ; map }
render m as JSON
Чтобы исключить свойства, вам нужно будет сделать что-то вроде этого (UNTESTED)
def exclude = [ 'val3' ]
Map m = new DefaultGrailsDomainClass( MyClass.class ).properties.findAll {
!( it.name in exclude )
}.inject( [:] ) { map, val ->
map."$val.name" = a."$val.name" ; map
}
render m as JSON
Если вы просто хотите отобразить экземпляр MyClass
как JSON, исключая определенные свойства, вот решение, которое использует класс JSONBuilder
, предоставляемый Grails
import grails.web.JSONBuilder
class MyClassController{
def someAction = {
def myClass = new MyClass()
def builder = new JSONBuilder.build {
myClass.properties.each {propName, propValue ->
// Properties excluded from the JSON
def excludes = ['class', 'metaClass', 'val3']
if (!excludes.contains(propName)) {
setProperty(propName, propValue)
}
}
render(text: builder.toString(), contentType: 'application/json')
}
}
Плагин JSON Exclusion Marshaller
Мне нужно было решить эту проблему в последнее время. Я пошел вперед и упаковал решение в плагин, который позволяет легко исключить свойства класса из выходного сигнала JSON. Он доступен на портале плагинов Grails.
После установите плагин, у вас будет доступ к методу класса grails.converters.JSON, называемому excludeFor *().
Более обширную документацию можно найти здесь: Как использовать маркерщик исключения JSON
Но в основном он может использоваться как таковой:
import grails.converters.JSON
def json, resultTeachersWillSee, resultOtherStudentsWillSee
// Given a TestStudent Domain Class
def student = new TestStudent([
firstName: "Tobias",
lastName: "Funke",
gradePointAverage: 3.6,
studentID: "FS-210-7312",
socialSecurityNumber: "555-55-5555"
])
student.save(flush: true)
// When
JSON.excludeForTeachers(TestStudent, ['socialSecurityNumber', 'id', 'class'])
JSON.use('excludeForTeachers') {
json = new JSON(student)
}
resultTeachersWillSee = json.toString()
// Then
assert resultTeachersWillSee == '{"firstName":"Tobias",
"gradePointAverage":3.6, "lastName":"Funke",
"studentID":"FS-210-7312"}'
// And When
JSON.excludeForOtherStudents(TestStudent, ['gradePointAverage', 'studentID',
'socialSecurityNumber', 'id', 'class'])
JSON.use('excludeForOtherStudents') {
json = new JSON(student)
}
resultOtherStudentsWillSee = json.toString()
// Then
assert resultOtherStudentsWillSee == '{"firstName":"Tobias",
"lastName":"Funke"}'
JSON.excludeForTeachers(...) создает именованный объект-маршаллер, называемый "excludeForTeachers". Маршаллер исключает три свойства объекта-ученика из полученного результата JSON. свойство "socialSecurityNumber" явно определено в классе, а свойство "id" было добавлено GORM за кулисами. В любом случае, учителям не нужно видеть какие-либо из этих свойств.
Плагин служит мне хорошо... Я надеюсь, что другие тоже будут полезны.