Ответ 1
из документов:
// 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)
Я реализую веб-службу RESTful, где пользователь должен отправить подписанный токен проверки вместе с запросом, чтобы я мог убедиться, что запрос не был подделан средним человеком. Моя текущая реализация такова.
Ток подтверждения - это объект 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.
Ex: один раз это будет
{"prop1":12345,"prop2":67890}
а в другой раз это будет
{"prop2":67890,"prop1":12345}
Итак, если клиент сериализовал экземпляр VerifData, как в первую строку, существует 50% вероятность его провала, даже если это правильно.
Есть ли способ обойти это? Могу ли я указать порядок свойств для отображения ObjectMapper (например, в порядке возрастания)? Или существует какой-либо другой способ наилучшего осуществления этого этапа проверки. И клиентские, и серверные реализации разработаны мной. Я использую Java Security API для подписания и проверки.
из документов:
// 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)
Аннотации полезны, но могут быть болью повсеместно применяться. Вы можете настроить весь ObjectMapper таким образом, чтобы
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
В Spring Boot вы можете добавить это поведение глобально, добавив следующее в класс точки входа Application
:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
return builder;
}
В Spring загрузке проще, указав свойство (в application.properties
например:
spring.jackson.mapper.sort_properties_alphabetically=true
От Дункана Макгрегора ответ: Его лучше использовать так:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
поскольку MapperFeature предназначен для XML файлов и поставляется с базой данных jackson-databind, которая не требуется...
В Jackson 2.x, который вы, вероятно, используете сегодня, используйте:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
Если вы заботитесь о внешности, вы также можете рассмотреть SerializationFeature.INDENT_OUTPUT
.
Обратите внимание, что для правильной сортировки вы должны сериализовать Карты или объекты. Если вы сериализуете 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"
}
}