Java Jackson ObjectMapper-指定对象属性的序列化顺序
我正在实现一个RESTful web服务,其中用户必须随请求一起发送一个签名的验证令牌,这样我就可以确保请求没有被中间人篡改。我当前的实现如下 验证令牌是一个VerifData对象,序列化为字符串,然后进行哈希和加密Java Jackson ObjectMapper-指定对象属性的序列化顺序,java,json,serialization,jackson,Java,Json,Serialization,Jackson,我正在实现一个RESTful web服务,其中用户必须随请求一起发送一个签名的验证令牌,这样我就可以确保请求没有被中间人篡改。我当前的实现如下 验证令牌是一个VerifData对象,序列化为字符串,然后进行哈希和加密 class VerifData { int prop1; int prop2; } 在我的服务中,我将要序列化的数据放入VerifData实例中,然后使用Jackson ObjectMapper对其进行序列化,并将其与验证令牌一起传递给验证引擎 VerfiData
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}
还有一次会是
{"prop1":12345,"prop2":67890}
{"prop2":67890,"prop1":12345}
因此,如果客户端已将VerifData实例序列化为第一个字符串,则即使它是正确的,也有50%的几率失败
有没有办法绕过这个问题?我是否可以指定ObjectMapper映射属性的顺序(如升序)?或者是否有任何其他方法可以最好地实施此验证步骤。客户端和服务器实现都是由我开发的。我使用Java安全API进行签名和验证。来自:
注释是有用的,但在任何地方应用都会很麻烦。您可以将整个
ObjectMapper
配置为以这种方式使用
当前版本:
objectMapper.configure(MapperFeature.SORT\u PROPERTIES\u字母顺序,true)
旧版本的杰克逊:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_字母顺序,true)代码>来自邓肯·麦格雷戈的回答:
最好是这样使用:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
由于MapperFeature适用于XMLs,并且附带jackson databind,这是不需要的…在Spring Boot中,您可以通过将以下内容添加到应用程序的入口点类来全局添加此行为:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
return builder;
}
通过指定属性(在application.properties
中,例如:
spring.jackson.mapper.sort_properties_alphabetically=true
在您今天可能正在使用的Jackson 2.x中,请使用:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
如果你关心外观,你也可以考虑<代码>序列化特性。
请注意,必须序列化映射或对象才能正确排序。例如,如果序列化
JsonNode
(从readTree
),则不会正确缩进
例子
结果:
{
"hello" : {
"cruel" : "world"
}
}
不使用标志参数:
objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
需要以下2ObjectMapper配置:
ObjectMapper.configure(MapperFeature.SORT\u PROPERTIES\u字母顺序,true)
或
ObjectMapper.enable(MapperFeature.SORT\u PROPERTIES\u按字母顺序)
定义用于POJO字段的属性序列化顺序
注意:是否不适用于java.util.Map
序列化
和
ObjectMapper.configure(SerializationFeature.ORDER\u MAP\u ENTRIES\u BY\u key,true)
或
ObjectMapper.enable(序列化功能。按键排序映射条目)
确定在序列化之前是否先按键对java.util.Map
项进行排序的功能
Spring启动配置示例(yaml):
spring:
杰克逊:
制图员:
按字母顺序对属性进行排序:true
序列化:
按键排序映射条目:true
您可以使用mix-in并根据需要指定属性的顺序:
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public final class ObjectMapperUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
MAPPER.addMixIn(Object.class, IdFirst.class);
}
@Bean
public ObjectMapper objectMapper() {
return MAPPER;
}
@JsonPropertyOrder({"id", "...", "..."})
private abstract static class IdFirst {}
}
我意识到这是一条老线索,但由于我正在寻找答案并在这里登陆,一些额外的信息可能对其他人很方便。
我当前使用的@JsonProperty注释(jackson-annotations-2.11.2)除了接受“value”参数外,还接受一个“index”(数字)参数,指定序列化过程中字段的顺序。我今天发现了另一种方法,以防字母顺序不是您所需的排序顺序。结果表明,在字段上添加@JsonProperty注释时,如果其余字段未注释,则会在写入时将其放在最后。我发现,当我要指定属性时不符合java命名约定的y名称
通过添加索引属性,您可以定义顺序。最低索引放在第一位
@JsonProperty(index=20)
String prop1;
@JsonProperty(index=10)
String prop2;
将导致:
{"prop2": "valueProp2", "prop1": "valueProp1"}
从下面提到的链接“所有codehaus服务都已终止”,如果您的目标是在任何地方应用排序,而不是在序列化特定对象时,请参见。这并不完全正确(或者至少不适用于所有场景)--请参阅,以获得一个有效的完整示例。@user2089674-您的示例仅适用于映射键。OP请求了对象字段的解决方案。只有一个映射项。因此,我看不到它的顺序。