我正在Jersey
上构建REST服务,并使用Jackson
从我的模型的java类生成JSON。模型具有绝对简单的值,我认为这是最典型的情况。但是我得到了奇怪的结果:
[{\"name\":\"Nick\",\"role\":\"admin\",\"age\":\"32\",\"rating\":47}]
我期待的结果:
[{"name":"Nick","role":"admin","age":"32","rating":47}]
我的字段源值不包含任何特殊字符。这些都很简单。
有我的Java课程。实体:
public class User {
private String name;
private String role;
private String age;
private Integer rating;
休息服务类别:
@ServiceConfig(contextName = "myContext")
@Path("/myrest")
public class MyRestService {
private static final String JSON_CONTENT_TYPE = MediaType.APPLICATION_JSON + ";charset=UTF-8";
@Context
protected HttpServletResponse response;
@GET
@Path("/users")
@OpenTransaction
@Produces({MediaType.APPLICATION_JSON})
public String findUsers(@QueryParam("department") String department) {
response.setContentType(JSON_CONTENT_TYPE);
PDTResponse.status(response).sendStatus(Response.Status.OK.getStatusCode());
List<User> users = new ArrayList<>();
users.add(new User("Nick", "admin", "32", 47));
String jsonInString;
ObjectMapper mapper = new ObjectMapper();
try {
jsonInString = mapper.writeValueAsString(users);
} catch (JsonProcessingException ex) {
jsonInString = "thrown exception: " + ex.getMessage();
}
return jsonInString;
}
我试图使用注释@JsonRawValue
作为字符串属性:
@JsonRawValue
private String name;
但在这种情况下的结果是:
[{\"name\":Nick,\"role\":admin,\"age\":32,\"rating\":47}]
我希望:
[{"name":"Nick","role":"admin","age":"32","rating":47}]
很明显,杰克逊以某种方式逃脱了结果json中的引用。但为什么要这样做,最重要的是如何避免呢?他们自己只是字符串!没有任何引号或特殊字符。
我使用Java 7
和Jackson 2.6.1
。并且Postman
测试结果。有什么想法来解决我的问题吗?
java中的所有字符串都必须转义它们中的引号。所以jsonInString应该有斜杠。当你输出jsonInString虽然它不应该有引号。你是在调试器中看它吗?
您可以配置ObjectMapper:
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
String jsonUsers = mapper.writeValueAsString(users);
更多信息here
看起来你正在使你的JAX-RS资源类复杂化。
要将Jackson用作Jersey 2.x的JSON提供程序,您不需要像这样创建一个ObjectMapper
实例。有一种更好的方法来实现它。继续阅读以了解更多详情。
要将Jackson 2.x用作JSON提供程序,您需要将jersey-media-json-jackson
模块添加到pom.xml
文件中:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.25.1</version>
</dependency>
然后在JacksonFeature
/ Application
子类中注册ResourceConfig
:
@ApplicationPath("/api")
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(JacksonFeature.class);
return classes;
}
}
@ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(JacksonFeature.class);
}
}
如果您没有Application
/ ResourceConfig
子类,则可以在JacksonFeature
部署描述符中注册web.xml
。可以用逗号分隔的jersey.config.server.provider.classnames
初始化参数值提供特定资源,提供程序和功能完全限定的类名。
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
</init-param>
杰克逊提供的MessageBodyWriter
是JacksonJsonProvider
。有关如何使用Jackson作为JSON提供程序的更多详细信息,请查看此answer。如果您需要自定义ObjectMapper
,请参阅此answer。
通过使用上述方法,您可以将资源类简单化为:
@Path("/users")
public class MyRestService {
@GET
@Produces({MediaType.APPLICATION_JSON + ";charset=UTF-8"})
public List<User> findUsers() {
List<User> users = new ArrayList<>();
users.add(new User("Nick", "admin", "32", 47));
return Response.ok(users).build();
}
在请求此类端点时,它将为您提供预期的JSON作为结果。
我也有同样的问题,尝试了不同的解决方案,但不起作用。问题不在于映射器,而在于映射器的输入。在你的情况下:
jsonInString = mapper.writeValueAsString(users);
'users'是一个集合。您需要将每个用户转换为JSONObject
,将其添加到JSONArray
然后使用数组上的映射器:像这样
JSONArray users = new JSONArray();
for (Collection user : usersCollection) {
JSONObject user = new JSONObject(mapper.writeValueAsString(user));
users.put(user);
}
mapper.writeValueAsString(user));
它应该不是问题,只需要在javascript中解析并使用它:JSON.parse(response)
如果您使用Spring和@ControllerAdvice for JSONP,那么为JSON字符串创建一个包装器并在属性上使用@JsonRawValue。 JSONP @ControllerAdvice不会包装String响应,它需要一个Object。
public class JsonStringResponse {
@JsonValue
@JsonRawValue
private String value;
public JsonStringResponse(String value) {
this.value = value;
}
}
@GetMapping
public ResponseEntity<JsonStringResponse> getJson() {
String json = "{"id":2}";
return ResponseEntity.ok().body(new JsonStringResponse(json));
}
@ControllerAdvice
public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpControllerAdvice() {
super("callback");
}
}
响应是一个json对象{"id":2}
如果有回调参数,则响应为callbackparameter({"id":2});