2013-04-08 7 views
3

org.springframework.validation.FieldError에 대한 맞춤 마샬 러를 만들려고하므로 MyCommandObject.errors을 포함하는 내 JSON 응답에 관련이없고 중요한 데이터를 넣지 않도록 할 수 있습니다.Grails JSON marshaller for FieldErrors

그러나 FieldError marshaller가 전혀 작동하지 않습니다. 이것이 나의 BootStrap.groovy에서 init 메소드로 가지고있는 것입니다.

def fieldErrorMarshaller = { 
     log.info("field error marshaller $it") 
     def returnArray = [:] 

     returnArray['field'] = it.field 
     returnArray['message'] = it.message 

     return returnArray 
    } 

    JSON.registerObjectMarshaller(FieldError, fieldErrorMarshaller) 

marshaller 로깅이나 오류가 표시되지 않습니다. 어떤 생각이 잘못되었을 지 모릅니다.

+0

우선 순위를 설정하려고 시도 했습니까? 'registerObjectMarshaller (java.lang.Class clazz, int priority, groovy.lang.Close callable)' – Bart

답변

5

Grails는 모든 오류를 처리하는 ValidationErrorsMarshaller의 인스턴스를 등록하므로 FieldError 마샬 러가 절대 호출되지 않습니다. ConvertersGrailsPlugin (플러그인의 설명) 당신이 당신의 요구를 (테스트하지 맞게 marshalObject()을 무시하고 다른 빈을 생성하고 같은 이름으로 등록 할 수 있도록이, 스프링 빈으로 등록되어 보면

//convertAnother is not called for each error. That's the reason of your custom marshalled not been called. 
for (Object o : errors.getAllErrors()) { 
    if (o instanceof FieldError) { 
     FieldError fe = (FieldError) o; 
     writer.object(); 
     json.property("object", fe.getObjectName()); 
     json.property("field", fe.getField()); 
     json.property("rejected-value", fe.getRejectedValue()); 
     Locale locale = LocaleContextHolder.getLocale(); 
     if (applicationContext != null) { 
      json.property("message", applicationContext.getMessage(fe, locale)); 
     } 
     else { 
     ... 

,해야 할 수도 있습니다 더 많은 코드).

class MyErrorsMarshaller implements ObjectMarshaller<JSON>, ApplicationContextAware { 
    ApplicationContext applicationContext; 

    public boolean supports(Object object) { 
     return object instanceof Errors; 
    } 

    public void marshalObject(Object object, JSON json) throws ConverterException { 
    ... 
    } 

} 

resources.groovy ValidationErrorsMarshaller위한

jsonErrorsMarshaller(MyErrorsMarshaller) 

errorsJsonMarshallerRegisterer(ObjectMarshallerRegisterer) { 
    marshaller = { MyErrorsMarshaller om -> } 
    converterClass = grails.converters.JSON 
} 

참조.

ConvertersGrailsPlugin에 대한 참조.

호기심있는 사람들을위한
+0

고맙다. 내 자신이 –

+0

링크가 죽었다고 생각하면 영원히 그랬을 것이다. – adeady

3

, 이것은 내가 세르지오 미 헬스 '대답의 기반으로 Bootstrap.groovy 쓰기 결국 발리는

def validationErrorsMarshaller = { 
    return it.getAllErrors().collect { 
     if (it instanceof FieldError) { 
      Locale locale = LocaleContextHolder.getLocale(); 
      def msg = messageSource.getMessage(it, locale) 

      return [ field: it.getField(), message: msg ] 
     } 
    } 
} 

JSON.registerObjectMarshaller(ValidationErrors, validationErrorsMarshaller) 

나는 MessageSource를를 사용하여 원래의 자바 마샬에서이 작업을 단순화 할 수 있었던 BootClock 클래스에 def messageSource을 추가하여 주입됩니다.

+0

이것은 수락 된 답변이어야합니다. IMHO – ebernie

0
//usage in grails controller 
render domainObject.errors as JSON 

//resources.groovy 
jsonErrorsMarshaller(MyErrorsMarshaller) 
errorsJsonMarshallerRegisterer(ObjectMarshallerRegisterer) { 
    marshaller = { MyErrorsMarshaller om -> } 
    converterClass = grails.converters.JSON 
} 

//grails.converters.JSON marshaller class 
import grails.converters.JSON 
import grails.validation.ValidationErrors 
import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException 
import org.codehaus.groovy.grails.web.converters.marshaller.ObjectMarshaller 
import org.codehaus.groovy.grails.web.json.JSONWriter 
import org.springframework.context.ApplicationContext 
import org.springframework.context.ApplicationContextAware 
import org.springframework.context.i18n.LocaleContextHolder 
import org.springframework.validation.Errors 
import org.springframework.validation.FieldError 
import org.springframework.validation.ObjectError 


class MyErrorsMarshaller implements ObjectMarshaller<JSON>, ApplicationContextAware { 
    ApplicationContext applicationContext; 

    public boolean supports(Object object) { 
     return object instanceof Errors; 
    } 

    public void marshalObject(Object object, JSON json) throws ConverterException { 
     JSONWriter writer = json.getWriter(); 
     try { 
      List<ObjectError> errors = ((ValidationErrors)object).getAllErrors() 
      writer.object(); 
      writer.key("errors").array(); 
      Locale locale = LocaleContextHolder.getLocale(); 
      for(FieldError error : errors){ 
       FieldError fe = (FieldError) error; 
       writer.object(); 
       writer.key("field").value(fe.getField()).key("message").value(applicationContext.getMessage(fe, locale)); 
       writer.endObject(); 
      } 
      writer.endArray(); 
      writer.endObject(); 
     } catch (ConverterException ce) { 
      throw ce; 
     } catch (Exception e) { 
      e.printStackTrace() 
      throw new ConverterException("Error converting Bean with class " + object.getClass().getName(), e); 
     } 
    } 
}