38

オブジェクトを JSON 文字列としてデータベースに保存しています。これらの文字列を公開する REST サービスを作成したいと考えています。ただし、メソッドを記述すると、返される文字列の引用符がエスケープされます。たとえば、文字列を返すメソッドを含めました。

@RequestMapping(value = "test", method = RequestMethod.GET)
public @ResponseBody
String getTest() {
    return "{\"a\":1, \"b\":\"foo\"}";
}

しかし、ブラウザでこのメソッドを呼び出すと、「{\"a\":1, \"b\":\"foo\"}」が返されます, "b": "foo"}. 戻り値の型が「String」である可能性が高いと思いますが、他に何ができるでしょうか。ラッパー クラスは同じことを行います。

{
  "value" : "{\"a\":1, \"b\":\"foo\"}"
}

シリアル化してからオブジェクトを返すこともできますが、それは少しばかげているようです。これは、おそらく私の構成ファイルの関連部分です。

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    super.configureMessageConverters(converters);
    converters.add(mappingJacksonHttpMessageConverter());
}

@Bean
MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
    MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
    mappingJacksonHttpMessageConverter.setObjectMapper(objectMapper);
    mappingJacksonHttpMessageConverter.setPrettyPrint(true);
    return mappingJacksonHttpMessageConverter;
}

ありがとう

編集: 以下で提案されているように、文字列が二重にエンコードされているようです。私の構成で 2 つのクラスをコメントアウトすると、この問題が修正されます。ただし、オブジェクトを返したい場所が他にもあり、構成する場所がわかっている共通のシリアル化 Bean を介してそれらを実行し続けたいと考えています。したがって、私は自分のオプションを次のように考えています。 a) すべてのシリアル化を自分で行う。すべてのメソッドは文字列を返し、すでに JSON であるメソッドはそれ自体を返し、オブジェクトであるメソッドはすべて JSONUtil.toJson(object) を返します。私はこのアプローチが好きではありませんが、うまくいくことはわかっています。b) 次のようなラッパー クラスを使用します。

public static class Wrapper {

    @JsonRawValue
    private final String value;
}

これは、実際の意味はありませんが、フロントにぎこちない「値」をもたらします。

基本的に私が欲しいのは @JsonRawValue ですが、プロパティではなく RequestMapping メソッドで機能させる必要があります。考え?意見?他の提案?

4

9 に答える 9

29

あなたが望むのは、 content-type で応答を生成することだと思いますapplication/json。あなたの場合、json-dataを生の文字列として持っている場合は、次のようにします。

コントローラーで属性に追加produces="application/json"します。@RequestMapping

@RequestMapping(value = "test", method = RequestMethod.GET, produces="application/json")
public @ResponseBody
String getTest() {
    return "{\"a\":1, \"b\":\"foo\"}";
}

次にStringHttpMessageConverter、application/json メディア タイプを受け入れるように を構成する必要があります。

Java-config を使用:

@Override
public void configureMessageConverters(
        List<HttpMessageConverter<?>> converters) {
    StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(
            Charset.forName("UTF-8"));
    stringConverter.setSupportedMediaTypes(Arrays.asList( //
            MediaType.TEXT_PLAIN, //
            MediaType.TEXT_HTML, //
            MediaType.APPLICATION_JSON));
    converters.add(stringConverter);
}

XML 構成の場合:

<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <array>
            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="application/json; charset=UTF-8" />
            </bean>
        </array>
    </property>
</bean>
于 2013-11-13T11:02:05.507 に答える
11

私はこれを使用しました:

@RequestMapping(..)
@ResponseBody
public JsonNode myGetRequest(){
...
//rawJsonString is the raw Json that we want to proxy back to the client
return objectMapper.readTree(rawJsonString);
}

そして、Jackson コンバーターは、JsonNode をプレーンな Json に変換する方法を知っていました。

于 2013-07-17T20:46:49.000 に答える
4

私の場合、レスポンス タイプをリクエスト パラメータによって決定する必要があったため、コードでコンテンツ タイプを指定する必要がありました。

@RequestMapping("/myurl")
public void radiusSearch(@RequestParam responseType, HttpServletResponse response) throws IOException {
    String jsonResponse = makeSomeJson();
    response.setContentType(responseType);
    try {
        response.getOutputStream().write(jsonResponse.getBytes());
    } finally {
        response.getOutputStream().close();
    }
}
于 2015-07-20T15:38:24.157 に答える
1

\"、文字"がエスケープされていることを意味します。これは標準です。そのように印刷されている場合は、おそらくオブジェクトを二重にシリアル化しています。

于 2013-03-19T18:04:41.277 に答える