有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Jackson ObjectMapper指定对象属性的序列化顺序

我正在实现一个RESTful web服务,其中用户必须随请求一起发送一个签名的验证令牌,这样我就可以确保请求没有被中间人篡改。我当前的实现如下

验证令牌是一个VerifData对象,序列化为字符串,然后进行哈希和加密

class VerifData {
    int prop1;
    int prop2;
}

在我的服务中,我将要序列化的数据放入VerifData实例中,然后使用Jackson ObjectMapper对其进行序列化,并将其与验证令牌一起传递给验证引擎

VerfiData verifData = new VerifData(12345, 67890);
ObjectMapper mapper = new ObjectMapper();
String verifCodeGenerated = mapper.writeValueAsString(verifData);

但似乎每次启动应用程序容器时,ObjectMapper映射到字符串的属性顺序都会发生变化

有一次是这样

{"prop1":12345,"prop2":67890}

还有一次会是

{"prop2":67890,"prop1":12345}

因此,如果客户端已将VerifData实例序列化为第一个字符串,则即使它是正确的,也有50%的几率失败

有没有办法绕过这个问题?我是否可以指定ObjectMapper映射属性的顺序(如升序)?或者是否有任何其他方法可以最好地实施此验证步骤。客户端和服务器实现都是由我开发的。我使用Java安全API进行签名和验证


共 (6) 个答案

  1. # 1 楼答案

    注释是有用的,但在任何地方应用都会很麻烦。您可以将整个ObjectMapper配置为以这种方式使用

    当前版本:

    objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)

    旧版本的杰克逊:

    objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);

  2. # 2 楼答案

    Jackson Annotations documentation开始:

    // ensure that "id" and "name" are output before other properties
    @JsonPropertyOrder({ "id", "name" })
    
    // order any properties that don't have explicit setting using alphabetic order
    @JsonPropertyOrder(alphabetic=true)
    
  3. # 3 楼答案

    需要以下2ObjectMapper配置:

    ObjectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)

    ObjectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)

    defines the property serialization order used for POJO fields
    Note: does not apply to java.util.Map serialization!


    ObjectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)

    ObjectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)

    Feature that determines whether java.util.Map entries are first sorted by key before serialization


    Spring启动配置示例(yaml):

    spring:
      jackson:
        mapper:
          SORT_PROPERTIES_ALPHABETICALLY: true
        serialization:
          ORDER_MAP_ENTRIES_BY_KEYS: true
    
  4. # 4 楼答案

    在Spring Boot中,您可以通过向Application入口点类添加以下内容来全局添加此行为:

      @Bean
      public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
    
        return builder;
      }
    
  5. # 5 楼答案

    通过指定属性(在application.properties中),在Spring引导中有一种更简单的方法,例如:

    spring.jackson.mapper.sort_properties_alphabetically=true
    
  6. # 6 楼答案

    在杰克逊2。x、 您今天可能正在使用的,请使用:

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
    

    如果你关心外表,你也可以考虑^ {CD1>}。

    请注意,必须序列化映射对象,才能正确排序。例如,如果序列化一个JsonNode(从readTree),将无法正确缩进

    示例

    import com.fasterxml.jackson.databind.*;
    
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
    mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
    
    String input = "{\"hello\": {\"cruel\" : \"world\"} }";
    Object pojo = mapper.readValue(input, Object.class);
    System.out.println(mapper.writeValueAsString(pojo));
    

    结果:

    {
      "hello" : {
        "cruel" : "world"
      }
    }