杰克逊在json中添加了反斜杠

Fra*_*ète 14 java rest json jersey jackson

我正在构建REST服务Jersey并使用Jackson从我的模型的java类生成JSON.模型具有绝对简单的值,我认为这是最典型的情况.但是我得到了奇怪的结果:

[{\"name\":\"Nick\",\"role\":\"admin\",\"age\":\"32\",\"rating\":47}]
Run Code Online (Sandbox Code Playgroud)

我期待的结果:

[{"name":"Nick","role":"admin","age":"32","rating":47}]
Run Code Online (Sandbox Code Playgroud)

我的字段源值不包含任何特殊字符.这些都很简单.

有我的Java课程.实体:

public class User {

  private String name;

  private String role;

  private String age;

  private Integer rating;
Run Code Online (Sandbox Code Playgroud)

休息服务类别:

@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;
}
Run Code Online (Sandbox Code Playgroud)

我试过使用@JsonRawValue字符串属性的注释:

@JsonRawValue
private String name;
Run Code Online (Sandbox Code Playgroud)

但在这种情况下的结果是:

[{\"name\":Nick,\"role\":admin,\"age\":32,\"rating\":47}]
Run Code Online (Sandbox Code Playgroud)

我希望:

[{"name":"Nick","role":"admin","age":"32","rating":47}]
Run Code Online (Sandbox Code Playgroud)

很明显,杰克逊以某种方式逃脱了结果json中的引用.但为什么要这样做,最重要的是如何避免呢?他们自己只是字符串!没有任何引号或特殊字符.

我用Java 7Jackson 2.6.1.并Postman测试结果.有什么想法来解决我的问题吗?

tea*_*ran 5

java 中的所有字符串都必须转义其中的引号。所以 jsonInString 中应该有斜杠。当你输出 jsonInString 时,它不应该有引号。您是在调试器还是其他东西中查看它?

  • 好,当然!但**为什么杰克逊不明白**?我在调试中看到简单的字符串 `[{"name":"Nick",...`。但在 Postman 中,我得到的结果为 `[{\"name\":\"Nick\",...`。据我了解,调试中的值包含反斜杠以纠正调试中的显示字符串。但我需要用它做什么呢?真正的字符串不包含反斜杠。我需要在结果字符串中替换它们吗?我认为这很愚蠢,而且不起作用:`return jsonInString.replaceAll("\\\\", "")`。 (5认同)

小智 5

您可以配置 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);
Run Code Online (Sandbox Code Playgroud)

更多信息在这里

  • 这是一个好主意,但它对我来说并不合适。我得到结果 json `"[{name:\"Nick\"...`,但我需要 `[{"name":"Nick"...`。我尝试使用这些设置参数,但没有找到了工作组合。 (2认同)
  • [这些设置仅适用于属性名称,不适用于值。](https://github.com/FasterXML/jackson-databind/issues/715#issuecomment-76782907) (2认同)

小智 5

做这个。

ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().setCharacterEscapes(new JsonUtil().new CustomCharacterEscapes());
ObjectWriter writer = mapper.writer();

String jsonDataObject = mapper.writeValueAsString(configMap);       

public class CustomCharacterEscapes extends CharacterEscapes {

private final int[] _asciiEscapes;

    public CustomCharacterEscapes() {
       _asciiEscapes = standardAsciiEscapesForJSON();
       //By default the ascii Escape table in jackson has " added as escape string
       //overwriting that here.
       _asciiEscapes['"'] = CharacterEscapes.ESCAPE_NONE;
     }

     @Override
     public int[] getEscapeCodesForAscii() {
       return _asciiEscapes;
     }

     @Override
     public SerializableString getEscapeSequence(int i) {
       return null;
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 这应该是答案 (2认同)

cas*_*lin 2

看起来您的 JAX-RS 资源类过于复杂。

要将 Jackson 用作 Jersey 2.x 的 JSON 提供程序,您不需要创建ObjectMapper这样的实例。有一个更好的方法来实现它。继续阅读以了解更多详细信息。

添加 Jackson 模块依赖项

要使用 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>
Run Code Online (Sandbox Code Playgroud)

注册 Jackson 模块

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;
    }
}
Run Code Online (Sandbox Code Playgroud)
@ApplicationPath("/api")
public class MyApplication extends ResourceConfig {

    public MyApplication() {
        register(JacksonFeature.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您没有Application/子类,您可以在部署描述符中ResourceConfig注册。可以在初始化参数的逗号分隔值中提供特定的资源、提供者和功能完全限定类名称。JacksonFeatureweb.xmljersey.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>
Run Code Online (Sandbox Code Playgroud)

MessageBodyWriter杰克逊提供的是JacksonJsonProvider。有关如何使用 Jackson 作为 JSON 提供程序的更多详细信息,请查看此答案。如果需要自定义ObjectMapper,请参考这个答案

修复您的资源类别

通过使用上述方法,您的资源类可以简单如下:

@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();
}
Run Code Online (Sandbox Code Playgroud)

当请求此类端点时,它会为您提供预期的 JSON 结果。