2011-02-23 2 views
0

JSON을 비롯한 다양한 표현으로 Spring을 통해 RESTful 웹 서비스를 구성하고 있습니다. 나는 인터페이스가 대칭 적이기를 바랍니다. 즉, GET을 통해 JSON에 직렬화 된 객체의 형식이 POST/PUT이 받아 들일 수있는 형식이기도합니다. 불행히도 GET을 작동시킬 수는 있습니다.Spring MVC 3.0으로 대칭형 JSON 제작/사용

는 여기에 JSON 메시지 컨버터와보기로 구성되어 전송 및 JSON을받는 내 구성입니다 : 내가, 예를 들어, 책을 객체를 반환하는 GET와 컨트롤러를 공격

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <util:list> 
      <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> 
     </util:list> 
    </property> 
</bean> 

<bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="mediaTypes"> 
     <util:map> 
      <entry key="json" value="application/json"/> 
     </util:map> 
    </property> 
    <property name="defaultViews"> 
     <util:list> 
      <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/> 
     </util:list> 
    </property> 
</bean> 

, 그것은 이런 식으로 출력합니다. 나는 주위를 켜고 POST를 통해 일부 유사한 JSON을 재 제출 또는 PUT 경우

{"book":{"isbn":"1234","author":"Leo Tolstoy","title":"War and Peace"}} 

은 봄에 대한 Unrecognized field "book" (Class com.mycompany.Book), not marked as ignorable 불평, 그것을 소비 할 수 없다. 또한, "책"래퍼 요소를 제거하면 (차라리,하지만 무슨 일이 일어나는 지 알기 위해), 나는 나쁜 요청을받습니다. 두 경우 모두 내 컨트롤러 코드가 절대로 안됩니다.

여기 내 컨트롤러가 있습니다. JSON 전용 코드를 여러 개 표현할 수 있기 때문에 여기에 JSON 전용 코드 (마샬링/언 마샬링되는 클래스의 주석)를 사용하지 않을 것입니다. 스프링의 분리 된 MVC 인프라를 사용하고 싶습니다. 일의 (마샬링 /보기가 해결/등.) 구성 파일에 : 당신은 당신이 특정 POST 방법을 구성 할 수 있도록 컨트롤러 방법에 GET 사용하도록 지정하는

@RequestMapping(method=PUT, value="/books/{isbn}") 
@ResponseStatus(NO_CONTENT) 
public void saveBook(@RequestBody Book book, @PathVariable String isbn) { 
    book.setIsbn(isbn); 
    bookService.saveBook(book) 
} 

@RequestMapping(method=GET, value="/books/{isbn}") 
public ModelAndView getBook(@PathVariable String isbn) { 
    return new ModelAndView("books/show", "book", bookService.getBook(isbn)); 
} 

답변

1

, 나는 그것은 밝혀

:-) 후손을 위해 내 자신의 질문에 대답하고 그 내가 게시이 예제의 방법으로 표시 내 실제 코드에 해당하는 제어 방법 :

void saveBook(@RequestBody Book book, @PathVariable String isbn) 

void saveBook(@RequestBody Book book, @PathVariable Long isbn) 

그리고 가치 PA :

사실 더이 (: LongString를 참고)처럼 보인다 ssed는 Long (영숫자)으로 변환 될 수 없습니다. 그래서 ... 나는 망 쳤어! :-)

그러나 스프링은 그것에 대해별로 좋지 않았으며 단순히 400 Bad Request을 뱉어 냈습니다. 이것을 발견하기 위해 디버거를 첨부했습니다.

ModelAndView를 사용하면 외부 래퍼 요소가 생성되므로 어떻게 든 처리해야합니다 (JSPView 등을 지원하기 위해 ModelAndView 사용자에게 맡기기를 원함). 아마 사용자 정의보기를 제공해야 할 것입니다. 래퍼 요소


업데이트 :

그것은이 모델을 나타내는 개체의지도를 정렬 화 스프링에 의해 생성되는 것으로 나타났다. 이지도에는 "book"이라는 키가 있습니다 (클래스 이름에서 생성 된 이유는 간단히 책을 반환하더라도 마찬가지입니다). 여기에 더 좋은 방법을 찾을 때까지 주위에 hackish 방법입니다 :

/** 
* When using a Spring Controller that is ignorant of media types, the resulting model 
* objects end up in a map as values. The MappingJacksonJsonView then converts this map 
* to JSON, which (possibly) incorrectly wraps the single model object in the map 
* entry's key. This class eliminates this wrapper element if there is only one model 
* object. 
*/ 
public class SimpleJacksonJsonView extends MappingJacksonJsonView { 

    @Override 
    @SuppressWarnings("unchecked") 
    protected Object filterModel(Map<String, Object> model) { 
     Map<String, Object> filteredModel = (Map<String, Object>) super.filterModel(model); 
     if(filteredModel.size() != 1) return filteredModel; 
     return filteredModel.entrySet().iterator().next().getValue(); 
    } 
} 
+0

MappingJackson2JsonView에는 extractValueFromSingleKeyModel 속성이 있습니다. true로 설정하면 SimpleJacksonJsonView와 똑같이 동작합니다. – Felix

+0

이 질문의 시점에서, 나는 재산이 존재하지 않았다고 믿습니다. 감사! – SingleShot

0

참고 수신 모두 얻을 수있을하고 POST 양식 RESTFull 메소드, 다음과 같은 형식 :

@RequestMapping(method=GET, value="/books/{isbn}") 
public ModelAndView getBook(@PathVariable String isbn) { 
    return new ModelAndView("books/show", "book", bookService.getBook(isbn)); 
} 

@RequestMapping(method=POST, value="/books/{isbn}") 
public ModelAndView getByPostBook(@PathVariable String isbn) { 
    return getBook(isbn); 
} 
+0

감사합니다. 나는 "POST로 얻고 싶지 않다", JSON 객체를 서버에 PUT 및/또는 POST (RESTful 서비스를 만들고있다)하고 싶다. 문제가 내 요청 매핑을 정의하는 방법이라고 생각하지 않지만 들어오는 JSON에 대한 메시지 변환기를 구성하는 방법은 무엇입니까? "PUT"태그가 붙은 예제 컨트롤러 메서드를 참조하십시오. 즉, 메시지 비 정렬 화에서 오류로 인해 호출 할 수없는 인터페이스입니다. – SingleShot

+1

Sory @SingleShot, 귀하의 질문을 이해하지 못한다고 생각하십시오. 글쎄, 만약 당신의 문제가 메시지 변환기에 있다면, 나는 당신이 자신의 것을 customyze해야한다고 생각합니다. 잭슨이 jason 객체를 작업 할 때 실제로하는 일이 마음에 들지 않습니다. 그래서 저는 Gson 메시지 변환기 인 Custon을 작성하여 숨겨진 방법을 발견했습니다. 새로운 아이디어를 얻는 데 도움이되는지 확인하십시오. (http://stackoverflow.com/questions/5019162/custom-httpmessageconverter-with-responsebody-to -do-json-things) – Iogui

+0

고마워요. 내 정확한 질문에 대답하지 않더라도 Gson에 대해 배울 수있었습니다 .-) – SingleShot

0

래퍼 북이없는 @SingleShot, { "isbn": "1234", "author": "Leo Tolstoy", "title": "War and Peace"}는 JSON에서 책 인스턴스를 올바르게 표현한 것입니다. GET 메소드에서 ModelAndView를 리턴 할 때 가지고있는 modelName "book"W book wrapper에서 MappingJacksonJSONView tacks로 인해 책 랩퍼가 추가됩니다.

더 나은 패턴은 당신은 당신이 당신의 요청을 확인할 수 있습니다, 단순히 PUT 올바른 컨트롤러 방법을 해결하지에 대해서 @ResponseBody

@RequestMapping(method=RequestMethod.GET, value="/books/{isbn}") 
public @ResponseBody Book getBook(@PathVariable String isbn) { 
    return new Book("isbn","title","author"); 
} 

과 방법을 당신의 가져 오기에 책 개체를 반환하고 주석하는 것 콘텐츠 유형을 application/json으로 지정합니다. 당황 비록

+0

고마워요. @ResponseBody 제안을 선호하지만 ModelAndView를 사용하면 HTML이 필요할 때 컨트롤러를 JSP로 변환 할 필요가 있습니다 (JSON 외에 HTML과 XML을 생성합니다). 나는 Content-Type을 application/json으로 설정했다. 그러나, 나는 당신의 제안을 탐구 할 것이다. – SingleShot

+0

필자가 제안한 스타일을 테스트했습니다. 동일한 결과가 있습니다 : "book"래퍼 요소. – SingleShot

+0

래퍼 요소에 해킹 된 솔루션이 있습니다. 내 대답을 보라. – SingleShot