java - 杰克逊序列化:包含正则表达式的字符串字段反转义以获取实际文字
问题描述
我有一个 DTO,String
其中包含一个包含正则表达式的类型字段。要成为有效的Java字符串,它包含double \
,因为第一个用于转义,这很容易理解。喜欢:
private final String regex = "myapp\\.\\w{2,3}\\/confirmation(.*)";
要使用的实际正则表达式是myapp\.\w{2,3}\/confirmation(.*)
.
而且,我将在 Kafka 消息中发送这个 DTO,序列化由 Jackson 完成。
ProducerRecord<String, String> record = new ProducerRecord<>(
kafkaTopicProperties.getTopic(),
String.valueOf(myDto.getOrderId()),
objectMapper.writeValueAsString(myDto)
);
可以理解的是,Jackson 无法区分普通字符串和正则表达式字符串,并将按原样发送转义的 Java 字符串。此外,在 JSON 中省略转义也是无效的(至少在我编辑.json
文件删除转义\
时,IntelliJ 显示解析错误),因此对于有效的 JSON,我还需要对其进行转义。正常到现在。
但是,Kafka 的消费者将收到一个转义的正则表达式字符串,并且必须对正则表达式进行反转义(删除多余的\
)。问题来了。句法变化导致语义差异。
实际上,因为 Kafka 对发送的内容没有限制,所以我们可以在发送之前自由地进行转义,因为它是纯文本。
但是,杰克逊能为我做这个魔术吗?
解决方案
感谢@Bohemian 和@NyamiouTheGaleanthrope
确实如您所说,我想我发现了问题:反序列化器应该org.springframework.kafka.support.serializer.JsonDeserializer
在 中Consumer
,而在生产者中,序列化器应该在org.springframework.kafka.support.serializer.JsonSerializer
. 那么一切都很好,我可以在日志中看到正则表达式没有额外的转义字符。我String(De)Serializer
以前用过。
双方的配置放在一起:
application.yml
:
spring:
kafka:
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer: # would be picked if you autowired the consumer
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties.spring.json.trusted.packages: '*'
制片人:
ProducerRecord<String, OrderMessageDto> record = new ProducerRecord<>(
kafkaTopicProperties.getTopic(),
String.valueOf(orderDto.getId()),
orderDto
);
kafkaTemplateOrder.send(record).get(kafkaTopicProperties.getTimeout(), TimeUnit.MILLISECONDS);
消费者(我只有一个消费者在测试,所以我必须手动配置):
@Autowired
private EmbeddedKafkaBroker kafkaBroker;
...
private ConsumerRecords consumeRecords(String topic) {
Map<String, Object> consumerProps = KafkaTestUtils.consumerProps(topic, "true", kafkaBroker);
consumerProps.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
consumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
JsonDeserializer<OrderPaymentUrlDto> valueDeserializer = new JsonDeserializer<>();
valueDeserializer.addTrustedPackages("*"); // necessary for include DTO as trusted type
ConsumerFactory<String, OrderPaymentUrlDto> factory = new DefaultKafkaConsumerFactory<>(
consumerProps,
new StringDeserializer(),
valueDeserializer
);
Consumer consumer = factory.createConsumer();
kafkaBroker.consumeFromAnEmbeddedTopic(consumer, topic);
return KafkaTestUtils.getRecords(consumer, 2000);
}
推荐阅读
- php - 我可以将自定义类转换为刀片 Laravel 中的变量吗
- json - 如何防止将“重复”JSON 条目插入表中
- java - java - 如何从包含灰度整数的文件文本中显示图像?
- python - Pyomo 对线性的非线性约束
- python - 从 scipy 分布数组中“检索”一个分布
- reactjs - Reacti18next 在 redux 上存储当前语言
- php - get_template_part if page has a custom taxonomy
- php - 如何使用 WordPress (PHP) 编写/读取和删除嵌套数组
- angular - StaticInjectorError(AppModule)[Overlay -> Injector]: StaticInjectorError(Platform: core)[Overlay -> Injector]
- gradle - Authorize.Net Java SDK 环境未设置问题