如何避免 Spring REST 控制器响应 returns JSON 字符串列表中的转义字符?

How to avoid escape characters in Spring REST Controller response that returns list of JSON strings?

用例:Return 来自 Spring Rest Controller 的 JSON 字符串列表(JSON 字符串来自第三方库)。

问题:来自 REST 控制器的响应包含转义字符。只有当 return 类型是列表或数组或任何其他集合类型时才会发生这种情况。 Return单个字符串工作正常。
如何 return 列表 JSON 格式化字符串但避免转义字符。

代码:

import java.util.Arrays;
import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("restjson")
public class RestJsonController {

    @GetMapping(value="list", produces = {MediaType.APPLICATION_JSON_VALUE})
    public List<String> getValues(){
        String value1 = "{\"name\":\"John\", \"age\":30}";
        String value2 = "{\"name\":\"Tom\", \"age\":21}";
        
        return Arrays.asList(value1, value2);
        //response has escape characters: 
        //["{\"name\":\"John\", \"age\":30}","{\"name\":\"Tom\", \"age\":21}"]
    }

    @GetMapping(value="single", produces = {MediaType.APPLICATION_JSON_VALUE})
    public String getValue(){
        String value1 = "{\"name\":\"John\", \"age\":30}";
        String value2 = "{\"name\":\"Tom\", \"age\":21}";
        
        return value1.concat(value2);
        //response has no escape characters: 
        //{"name":"John", "age":30}{"name":"Tom", "age":21}
    }
}

Spring引导版本:2.7.0
完整代码位于:https://github.com/rai-sandeep/restjson/blob/main/src/main/java/com/sdprai/restjson/controller/RestJsonController.java

编辑:
为了避免与字符串连接相关的任何混淆,我更新了代码(见下文)。 Return即使只有一个 JSON 字符串也会在响应中产生转义字符。但是 return 只是一个字符串没有这个问题。我不明白这种差异背后的原因。对于我的用例,有没有办法 return 没有转义字符的 JSON 字符串列表?

import java.util.Collections;
import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("restjson")
public class RestJsonController {

    @GetMapping(value="list", produces = {MediaType.APPLICATION_JSON_VALUE})
    public List<String> getValues(){
        String value1 = "{\"name\":\"John\", \"age\":30}";
        
        return Collections.singletonList(value1);
        //returns: ["{\"name\":\"John\", \"age\":30}"]
    }

    @GetMapping(value="single", produces = {MediaType.APPLICATION_JSON_VALUE})
    public String getValue(){
        String value1 = "{\"name\":\"John\", \"age\":30}";
        
        return value1;
        //returns: {"name":"John", "age":30}
    }
}

基本上,Spring MVC(spring 启动的一部分,负责处理 Rest 控制器等)通过转换常规 java 来处理 JSON 响应对象到有效的 json 字符串(没有反斜杠)。

所以问题是为什么您需要使用字符串? 试试下面的代码:

public class Person {
   private String name;
   private int age;
   // constructors, getters, etc.
}

 @GetMapping(value="list", produces = {MediaType.APPLICATION_JSON_VALUE})
    public List<Peron> getValues(){
        Person value1 = new Person("John", 30);
        Person value2 = new Person("Tom", 21);
        
        return Arrays.asList(value1, value2);

    }

现在,如果您说 {\"name\":\"John\", \"age\":30} 之类的字符串已经从某些第三方传给您,并且您有点“被迫”return List<String> 而不是 List<Person> 这就像在说 - 我不想 spring 为我转换任何东西,我会自己做。在这种情况下,您应该了解为什么您的第三方 return 的字符串是这样的以及您可以用它做什么

value1.concat(value2);

以上代码连接了两个字符串,因此结果字符串中不会产生转义字符。

        String value1 = "{\"name\":\"John\", \"age\":30}";
        String value2 = "{\"name\":\"Tom\", \"age\":21}";
        
        return Arrays.asList(value1, value2);

在上面的代码中,您向列表中添加了一个字符串。所以你会看到转义字符,即 \" for ".

如果您想要对象列表,请使用对象映射器或 GSON 库将字符串转换为对象,并将这些对象添加到列表中。

更新

您正在将 JSON(字符串)添加到列表中。所以你得到了一个带有转义字符的字符串。

还有另一种方法可以做到这一点。 创建一个 JSON 对象并将 response1 和 response2 添加到该对象和 return 该对象。

你可以试试这个避免转义。

@GetMapping(value="list", produces = {MediaType.APPLICATION_JSON_VALUE})
    public String getValues(){
        String value1 = "{\"name\":\"John\", \"age\":30}";
        String value2 = "{\"name\":\"Tom\", \"age\":21}";
        return Arrays.asList(value1, value2).toString();
    }

如果可行,请点赞并接受。