2013-10-06 9 views
16

SpringMVC 프로젝트에서 JSON 용 새 Java API (JSR 353)를 사용하고 있습니다.SpringMVC에서 @ResponseBody를 사용하여 JsonObject 반환

아이디어는 Json 데이터의 일부를 생성하여 클라이언트로 반환하는 것입니다. 나는이 같은 다소 모양이 컨트롤러 :이 액세스 할 때 대신 JSON의 예상 표현을 얻는,

@RequestMapping("/test") 
@ResponseBody 
public JsonObject test() { 
     JsonObject result = Json.createObjectBuilder() 
       .add("name", "Dade") 
       .add("age", 23) 
       .add("married", false) 
       .build(); 
     return result; 
    } 

을 그리고, 나는이 대신받을 : 왜이 ​​

{"name":{"chars":"Dade","string":"Dade","valueType":"STRING"},"age":{"valueType":"NUMBER","integral":true},"married":{"valueType":"FALSE"}} 

입니까? 무슨 일 이니? 그리고 JSON이 제대로 반환되도록하려면 어떻게해야합니까?

+2

어떤 API입니까? –

+0

API로 @SotiriosDelimanolis, 당신은 JsonObject를 언급하고 있습니까? 그것은 JSR 프로세싱을위한 JSR 353 : Java API입니다.Question updated too – dade

답변

22

새로운 JSR 353 API에 대해 특별한 HandlerMethodReturnValueHandler이 없다는 것을 알게되면 매우 간단합니다. 대신이 경우 RequestResponseBodyMethodProcessor (@ResponseBody의 경우)은 MappingJackson2HttpMessageConverter을 사용하여 처리기 메서드의 반환 값을 serialize합니다.

내부적으로 MappingJackson2HttpMessageConverterObjectMapper을 사용합니다. 기본적으로 ObjectMapper은 클래스의 getter를 사용하여 객체를 JSON에 직렬화합니다.

당신은 JSR 353의 Glassfish의 프로 바이더의 구현을 사용하는 가정하면, 그 클래스는 org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl, org.glassfish.json.JsonStringImplorg.glassfish.json.JsonNumberImpljavax.json.JsonValue$3 (값 FALSE에 대한 익명 클래스)입니다. JsonObjectImpl는 (당신의 결과, 즉. 루트, 객체)는 Map (특수 타입)입니다, ObjectMapper는지도 키가 JSON 키입니다 JSON 키 - 값 쌍 요소 및지도 값으로지도의 항목을 직렬화

때문에 JSON 값입니다. 키에 대해서는 name, agemarried과 같이 일련 번호가 올바르게 작동합니다. 값을 위해 위에서 언급 한 클래스와 각각의 getter 클래스를 사용합니다. 예를 들어, org.glassfish.json.JsonStringImpl

{"chars":"Dade","string":"Dade","valueType":"STRING"} 

같은 다른 분야에 대해 적용되는 그러므로 JsonStringImpl 객체 (즉, 맵 엔트리의 값) 직렬화 자바 빈 게터를 사용

final class JsonStringImpl implements JsonString { 

    private final String value; 

    public JsonStringImpl(String value) { 
     this.value = value; 
    } 

    @Override 
    public String getString() { 
     return value; 
    } 

    @Override 
    public CharSequence getChars() { 
     return value; 
    } 

    @Override 
    public ValueType getValueType() { 
     return ValueType.STRING; 
    } 
    ... 
} 

ObjectMapper로서 구현 .

JSON을 올바르게 작성하려면 String을 반환하면됩니다.

@RequestMapping("/test", produces="application/json") 
@ResponseBody 
public String test() { 
     JsonObject result = Json.createObjectBuilder() 
       .add("name", "Dade") 
       .add("age", 23) 
       .add("married", false) 
       .build(); 
     return result.toString(); 
} 

좀 더 복잡하지만 더 많은 보람을 느껴보세요.

+3

결과 JSON은''{\ "foo \": \ "bar \"} "와 같이 이스케이프 처리됩니다. –

+0

@DzmitryLazerka 어디에서 탈출 했습니까? 위의'test()'메소드는 아무 것도 빠지지 않습니다. –

+0

봄 메시지 변환기에서 테스트가 반환 된 후. 그 결과는 String이고 mime-type application/json은 JSON으로 변환되어야합니다. MappingJackson2HttpMessageConverter (Jackson이 WebMvcConfigurationSupport에있는 경우 기본적으로 추가됨)를 참조하십시오. 따라서 문자열을 JSON으로 변환하고 이스케이프하고 큰 따옴표를 추가합니다. –

1

Sotirios Delimanolis의 답변이 실제로 작동하지만, 제 경우에는 적절한 HttpMessageConverter 주문이 제대로 이루어져야합니다. JodaTime 값을 ISO 8601 형식으로 변환해야하기 때문입니다. 이 맞춤 WebMvcConfigurerAdapter 구성이 나를 위해 일했습니다 :

@Configuration 
public class WebConfiguration extends WebMvcConfigurerAdapter { 

@SuppressWarnings("UnusedDeclaration") 
private static final Logger log = LoggerFactory.getLogger(WebConfiguration.class); 

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    log.info("Configuring jackson ObjectMapper"); 
    final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 
    final ObjectMapper objectMapper = new ObjectMapper(); 

    //configure Joda serialization 
    objectMapper.registerModule(new JodaModule()); 
    objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature. 
      WRITE_DATES_AS_TIMESTAMPS, false); 

    // Other options such as how to deal with nulls or identing... 
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT); 
    converter.setObjectMapper(objectMapper); 

    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); 
    /* 
    StringHttpMessageConverter must appear first in the list so that Spring has a chance to use 
    it for Spring RestController methods that return simple String. Otherwise, it will use 
     MappingJackson2HttpMessageConverter and clutter the response with escaped quotes and such 
    */ 
    converters.add(stringHttpMessageConverter); 
    converters.add(converter); 
    super.configureMessageConverters(converters); 
} 
} 
관련 문제