有一种简洁的方法可以在Spring Web API中将字符串作为json返回吗?

时间:2017-06-01 21:58:15

标签: java json spring string serialization

例如,我必须按如下方式实施:

@RequestMapping(value = "/get-string", method = {RequestMethod.GET})
public @ResponseBody String getString() {
    return "Hello World!";
}

当Ajax在JS文件中调用该操作时,收到的响应是:HelloWorld。因此,如果Ajax请求配置为仅接收json编码的响应,则会收到标准的deconding错误。要在服务器端解决此问题,我需要收到"HelloWorld"

我的问题是:有一种干净的方法可以做到这一点,而不只是更改为下面的字符串返回的字符串?

    ...
    return "\"Hello World!\"";
}

更新说明:在这个问题的时候,我对我之前想要的返回JSON地图而不是单个字符串的解决方案感到满意。

但是现在,我花了一些时间来搜索这个,并尝试更多地了解JSON模式。

首先,我发现我的问题与这些问题重复onetwothree。正确的answer表示问题出在Spring Boot的默认序列化程序(Jackson的库)中,它将字符串值(序列化时)视为原始JSON字符串,因此它返回值正如我所料,双引号而不是添加。

恐惧,我会选择 Bh​​argav的answer,它更接近我想要的东西。 ddbullfrogRohaNayak的答案是正确的,但它们无法正确解决我的问题。 Ademir Constantino的comment也是正确的,他说使用普通/文本而不是json格式,使用这个reference。 Luay Absulraheem的answer是配置动作的正确方法,但它没有按照想要的方式工作,它继续将字符串作为原始json发送。 非常感谢您的回答!

此外,可以自定义Spring Boot以使用Gson作为其序列化器,如article所示。在您的项目上安装Gson依赖项之后,您只需在 application.properties 文件中添加此行:

...
spring.http.converters.preferred-json-mapper=gson

通过这种方式,您不必在每次要发送字符串值时进行解析 要通过Spring Boot序列化,并且在AJAX处理程序中没有双引号就不会收到它。

我试图实现与ASP.NET MVC相同的行为,后者使用JSON.NET library来执行序列化。这个以及AJAX接受单个字符串(例如" hello world")作为JSON的事实,使我对JSON模式进行了更深入的研究。

有多个"标准" JSON格式的定义。正如在Stack的其他question上所讨论的那样,当前的互联网标准" JSON值由RFC-8259定义,如文档第5页所述:

  

JSON值必须是对象,数组,数字或字符串,或者是其中之一   以下三个字面名称:

     
      
  •   
  •   
  •   

如上所示,在旧标准中,JSON可以是比以前更广泛的数据类型。

更新注释:另一种方法是返回char []而不是String 实例。这样,Spring Boot将无法识别为原始JSON字符串:

@RequestMapping(value = "/get-string", method = {RequestMethod.GET})
public @ResponseBody char[] getString() {
    return "Hello World!".toCharArray();
}

5 个答案:

答案 0 :(得分:3)

是的,您可以使用像gson或jackson这样的库将您的字符串转换为JSON,在那里为您提供如下所示的json输出。

Gson gson= new GsonBuilder().create();
    gson.toJson(Your String);

另外,别忘了添加 produces = MediaType.APPLICATION_JSON_VALUE暴露的方法,以便spring知道需要生成什么样的o / p。

答案 1 :(得分:2)

尝试将produces = {MediaType.APPLICATION_JSON_VALUE }添加到@RequestMapping,因为它会影响所写的实际内容类型。要使用UTF-8编码生成JSON响应,应使用produces = {MediaType.APPLICATION_JSON_UTF8_VALUE }

答案 2 :(得分:2)

解决方案

Spring在默认情况下配置了一个StringHttpMessageConverter,它可以处理从控制器返回的任何String,而与媒体类型无关,就好像它是text/plain

您可以通过在Spring中配置的所有其他消息转换器之后移动StringHttpMessageConverter或将其替换为自己的不处理*/*媒体类型的实现并进行配置来解决此问题。

在Spring引导中: 扩展WebMvcConfigurerAdapter,覆盖extendMessageConverters,并根据需要修改收到的列表,例如

@Configuration
public class StringHttpMessageConverterReorganizingWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter
{
    @Override
    public void extendMessageConverters(final List<HttpMessageConverter<?>> converters)
    {
        super.extendMessageConverters(converters);

        // do whatever you see fit with StringHttpMessageConverter in the converters list
        // ...
    }
}

此后,Jackson(可能还有其他JSON序列化程序)将在结果处理中表达自己的意见,并在响应中将My string序列化为"My string"


背景

当将结果处理到HTTP响应主体中时,Spring遍历其已注册的HttpMessageConverter,并选择与Java结果的类型和相应的媒体类型相匹配的第一个(例如,从@RequestMapping::produces开始)。

在这种情况下,控制器返回的结果类型为String,媒体类型为application/json或类似的内容。

在默认配置中,有一个名为StringHttpMessageConverter的消息转换器,它处理String返回类型以及媒体类型text/plain*/*。由于它通常是在用于处理json数据的任何其他序列化程序之前注册的,因此它将仅将任何String转换为其身份,并完成结果转换,将未加引号且未转义的字符串写入响应中不管我们的text/plain媒体类型如何,都好像application/json一样。

所以我们有以下选择:
(a)接管消息转换器的创建,并提供不同的顺序或不接受StringHttpMessageConverter的{​​{1}}。
(b)在选择转换器之前,接管消息转换器选择逻辑,并查看是否有比*/*更具体的匹配项。
(c)以某种方式侵入已创建的转换器并替换/更改/删除*/*

对于选项(a),这是不切实际的,因为
1. StringHttpMessageConverter always uses media type */*。滚动自定义实现是很有必要的。
2. StringHttpMessageConverter is final and cannot be overriden to choose different converters
3.使用中的另一个配置框架(例如Spring Boot)可以使用其自己的逻辑来提供消息转换器。例如,通过依赖项注入继承和使用WebMvcConfigurationSupport::addDefaultMessageConverters(例如,使用WebMvcConfigurationSupport)将导致MVC的Spring Boot自动配置停止。
覆盖配置框架中的消息转换器配置可能是可行的。我对Spring Boot的搜索仅达到了HttpMessageConverters类,该类支持忽略默认转换器,因此这也是一种实现方法。

选项(b)也不切实际。整个迭代逻辑是在AbstractMessageConverterMethodProcessor::writeWithMessageConverters中完成的,不幸的是,它还会执行其他工作,因此没有简单的方法可以覆盖它。

因此,我们到达选项(c),该选项概述了此答案的开始。

答案 3 :(得分:1)

只需创建一个包含键值的地图。它将达到目的。 每个JSON都需要一个键和一个值 map.put(“hello”:“你的字符串值”)

返回地图;

答案 4 :(得分:0)

您可以将json格式的String值返回给客户端;

返回&#34; {\&#34;回复\&#34;:\&#34; Hello World!\&#34;}&#34;;