将JSON返回给ResponseEntity<String>

46
我在控制器中有一个方法,应该返回一个字符串形式的JSON。它适用于非原始类型的JSON:
@RequestMapping(value = "so", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<String> so() {
    return new ResponseEntity<String>("This is a String", HttpStatus.OK);
}

curl的响应如下:

This is a String
4个回答

74
问题的根源在于Spring(通过ResponseEntityRestController和/或ResponseBody)将字符串的内容用作原始响应值,而不是将字符串视为要编码的JSON值。即使控制器方法使用produces = MediaType.APPLICATION_JSON_VALUE,这也是正确的,如此处的问题。

这就像以下示例之间的区别:

// yields: This is a String
System.out.println("This is a String");

// yields: "This is a String"
System.out.println("\"This is a String\"");

第一个输出无法解析为JSON,但第二个输出可以。
例如'"'+myString+'"可能不是一个好主意,因为它不能正确处理字符串内部的双引号转义,并且不会生成任何这样的字符串的有效JSON。
处理此问题的一种方法是将字符串嵌入对象或列表中,以便您不会将原始字符串传递给Spring。 但是,这会更改您的输出格式,而且如果您想要返回正确编码的JSON字符串,没有理由不这样做。 如果您想这样做,最好的方法是使用JSON格式化程序,例如JsonGoogle Gson。 使用Gson可能如下所示:
import com.google.gson.Gson;

@RestController
public class MyController

    private static final Gson gson = new Gson();

    @RequestMapping(value = "so", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> so() {
        return ResponseEntity.ok(gson.toJson("This is a String"));
    }
}

7
这是正确答案。你可能需要问自己,是否真的需要为仅返回字符串的此端点支持JSON。如果不需要,只需将"produces"更改为"text/plain"即可。 - CaptRespect
3
应该被接受为正确答案,而不是之前的答案。 - Dmytro Kryvenko

24
@RequestMapping(value = "so", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String so() {
    return "This is a String";
}

那绝对有效...你得到什么回应,你需要什么? - NimChimpsky
我得到This is a String,如果我返回一个对象,我得到 {"repeatSecond":15}。因此对于原始数据类型,似乎我没有得到 JSON 字符串,但对于对象,我确实得到了。 - Sydney
顺便说一下,我找到了你回答的相关帖子:https://dev59.com/4GnWa4cB1Zd3GeqP2qar - Sydney

4
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;

public ResponseEntity<?> ApiCall(@PathVariable(name = "id") long id) throws JSONException {
    JSONObject resp = new JSONObject();
    resp.put("status", 0);
    resp.put("id", id);

    return new ResponseEntity<String>(resp.toString(), HttpStatus.CREATED);
}

@RequestMapping(value = "/ApiCall/{id}", method = RequestMethod.POST, produces = "application/json") - user2308728
<dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20180813</version> <type>jar</type> </dependency> - user2308728

1

另一种解决方法是使用 String 的包装器,例如:

public class StringResponse {
    private String response;
    public StringResponse(String response) {
        this.response = response;
    }
    public String getResponse() {
        return response;
    }
}

然后在你的控制器方法中返回这个:
ResponseEntity<StringResponse>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接