2013-10-06 69 views
16

我在SpringMVC項目中爲JSON使用了新的Java API(JSR 353)。在SpringMVC中使用@ResponseBody返回JsonObject

這個想法是生成一些Json數據並將其返回給客戶端。控制器我看起來有點像這樣:

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

當我訪問它,而不是得到了JSON的預期表現,我得到這些來代替:

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

這是爲什麼?到底是怎麼回事?我該如何讓它正確返回預期的JSON?

+2

這是什麼API? –

+0

@SotiriosDelimanolis by API,你是指JsonObject?它是JSR 353:用於JSON處理的Java API。更新的問題也是 – dade

回答

22

當你意識到新的JSR 353 API沒有特別的HandlerMethodReturnValueHandler時,答案很簡單。相反,在這種情況下,RequestResponseBodyMethodProcessor(對於@ResponseBody)使用MappingJackson2HttpMessageConverter序列化處理程序方法的返回值。在內部,MappingJackson2HttpMessageConverter使用ObjectMapper。默認情況下,ObjectMapper使用類的getters將對象序列化爲JSON。

假設你正在使用Glassfish的了JSR 353的提供者實現,這些類是org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImplorg.glassfish.json.JsonStringImplorg.glassfish.json.JsonNumberImpl,並javax.json.JsonValue$3(該值FALSE匿名類)。

由於JsonObjectImpl(你的結果,即,根,對象)是Map(專用型),ObjectMapper串行化地圖的作爲JSON鍵值對元件,其中,所述地圖的鍵是JSON密鑰,以及地圖值項是JSON值。對於密鑰,它工作正常,序列化爲name,agemarried。對於該值,它使用我上面提到的類和它們各自的getter。例如,org.glassfish.json.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實現,因此使用的Java Bean的getter序列化JsonStringImpl對象(即地圖項目的價值),如

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

這同樣適用於其他領域。

如果要正確寫入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(); 
} 

或使自己的HandlerMethodReturnValueHandler,稍微複雜一點,但更有價值。

+3

但是結果JSON會被轉義,比如''{\「foo \」:\「bar \」}「',如何讓它返回JSON,就像'{」foo「:」bar「}'? –

+0

@DzmitryLazerka逃到哪裏?上面的'test()'方法不會轉義任何東西。 –

+0

在Spring消息轉換器中,測試返回後。它看到的結果是一個字符串,並且對於mime類型的應用程序/ 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); 
} 
} 
相關問題