- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个新的Deserializer,以便能够将空字符串写为null
public class CustomDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
JsonNode node = jsonParser.readValueAsTree();
if (node.asText().isEmpty()) {
return null;
}
return node.toString();
}
}
尝试在每个User字段上创建单个注释,“自定义”起作用,但是通过在整个类上插入注释,我不再能够打印Json消息
@JsonDeserialize(using = CustomDeserializer.class)
public class User {
private String firstName;
private String lastName;
private String age;
private String address; }
CustomExceptionHandler引发此错误:
类MethodArgumentNotValidException
public class KafkaConsumer {
@Autowired
private UserRepository userRepository;
@KafkaListener(topics = "${spring.kafka.topic.name}")
public void listen(@Validated User user) {
User user = new User(user);
UserRepository.save(user.getName(), user);
}
}
对象映射器
public ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(Include.NON_NULL);
return mapper;
}
是否有可能使它适用于整个类(class)?
最佳答案
如果您希望将表示整个整个对象的空String
视为null
,则可以启用默认情况下禁用的ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
Jackson deserialization feature。
您可以在配置ObjectMapper
时包括它:
public ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(Include.NON_NULL);
// Enable ACCEPT_EMPTY_STRING_AS_NULL_OBJECT deserialization feature
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
return mapper;
}
如上所述,当您要将代表整个对象的整个
的空String
视为null
时,这很有用;但是,它不适用于String
类型的单个属性:在以后的情况下,您可以安全地使用自定义反序列化器,因此,解决方案实际上是两种方法的组合,使用ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
反序列化功能来处理整个对象,和用于处理各个String
属性的自定义解串器。User
反序列化器。请考虑一下示例(为了清楚起见,我将名称重构为UserDeserializer
):import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
public class UserDeserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
JsonNode node = jsonParser.readValueAsTree();
Iterator<String> fieldNames = node.fieldNames();
// Process Jackson annotations looking for aliases
Map<String, String> fieldAliases = this.getAliases();
User user = new User();
boolean anyNonNull = false;
// Iterate over every field. The deserialization process assume simple properties
while(fieldNames.hasNext()) {
String fieldName = fieldNames.next();
JsonNode fieldValue = node.get(fieldName);
String fieldValueTextRepresentation = fieldValue.asText();
if (fieldValueTextRepresentation != null && !fieldValueTextRepresentation.trim().isEmpty()) {
// Check if the field is aliased
String actualFieldName = fieldAliases.get(fieldName);
if (actualFieldName == null) {
actualFieldName = fieldName;
}
this.setFieldValue(user, actualFieldName, fieldValueTextRepresentation);
anyNonNull = true;
}
}
return anyNonNull ? user : null;
}
// Set field value via Reflection
private void setFieldValue(User user, String fieldName, String fieldValueTextRepresentation) {
try {
Field field = User.class.getDeclaredField(fieldName);
Object fieldValue = null;
Class clazz = field.getType();
// Handle each class type: probably this code can be improved, but it is extensible and adaptable,
// you can include as many cases as you need.
if (clazz.isAssignableFrom(String.class)) {
fieldValue = fieldValueTextRepresentation;
} else if (clazz.isAssignableFrom(LocalDate.class)) {
// Adjust the date pattern as required
// For example, if you are receiving the information
// like this: year-month-day, as in the provided example,
// you can use the following pattern
fieldValue = LocalDate.parse(fieldValueTextRepresentation, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} else if (clazz.isAssignableFrom(Integer.class)) {
fieldValue = Integer.parseInt(fieldValueTextRepresentation);
}
field.setAccessible(true);
field.set(user, fieldValue);
} catch (Exception e) {
// Handle the problem as appropriate
e.printStackTrace();
}
}
/* Look for Jackson aliases */
private Map<String, String> getAliases() {
Map<String, String> fieldAliases = new HashMap<>();
Field[] fields = User.class.getDeclaredFields();
for (Field field: fields) {
Annotation annotation = field.getAnnotation(JsonAlias.class);
if (annotation != null) {
String fieldName = field.getName();
JsonAlias jsonAliasAnnotation = (JsonAlias) annotation;
String[] aliases = jsonAliasAnnotation.value();
for (String alias: aliases) {
fieldAliases.put(alias, fieldName);
}
}
}
return fieldAliases;
}
}
有了此序列化程序后,给出了一个类似于User
的类:import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@JsonDeserialize(using = UserDeserializer.class)
public class User {
private String firstName;
private String lastName;
private Integer age;
private String address;
@JsonAlias("dateofbirth")
private LocalDate dateOfBirth;
// Setters and getters omitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (firstName != null ? !firstName.equals(user.firstName) : user.firstName != null) return false;
if (lastName != null ? !lastName.equals(user.lastName) : user.lastName != null) return false;
if (age != null ? !age.equals(user.age) : user.age != null) return false;
if (address != null ? !address.equals(user.address) : user.address != null) return false;
return dateOfBirth != null ? dateOfBirth.equals(user.dateOfBirth) : user.dateOfBirth == null;
}
@Override
public int hashCode() {
int result = firstName != null ? firstName.hashCode() : 0;
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
result = 31 * result + (age != null ? age.hashCode() : 0);
result = 31 * result + (address != null ? address.hashCode() : 0);
result = 31 * result + (dateOfBirth != null ? dateOfBirth.hashCode() : 0);
return result;
}
以及以下JSON(我仅为了测试别名而更改为dateofbirth
字段的名称):{"firstName":"John","age":40,"dateofbirth":"1978-03-16"}
您应该获得适当的结果,请考虑以下测试: public static void main(String... args) throws JsonProcessingException {
User user = new User();
user.setFirstName("John");
user.setAge(40);
user.setDateOfBirth(LocalDate.of(1978, Month.MARCH, 16));
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String json = "{\"firstName\":\"John\",\"age\":40,\"dateofbirth\":\"1978-03-16\"}";
User reconstructed = mapper.readValue(json, User.class);
System.out.println(user.equals(reconstructed));
}
最后,请注意,为了允许您的@KafkaListener
处理null
值,您必须将@Payload
批注与required = false
结合使用,例如:public class KafkaConsumer {
@Autowired
private UserRepository userRepository;
@KafkaListener(topics = "${spring.kafka.topic.name}")
public void listen(@Payload(required = false) User user) {
// Handle null value
if (user == null) {
// Consider logging the event
// logger.debug("Null message received");
System.out.println("Null message received");
return;
}
// Continue as usual
User user = new User(user);
UserRepository.save(user.getName(), user);
}
}
请参阅相关的Spring Kafka documentation和此Github issue以及相关的commit。 This SO question也可能是相关的。
关于java - JsonDeserializer不适用于该类,而仅适用于该类的单个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66597864/
我在我的 Xcode 项目目录中输入了以下内容: keytool -genkey -v -keystore release.keystore -alias mykey -keyalg RSA \
假设我有一个像这样的 DataFrame(或 Series): Value 0 0.5 1 0.8 2 -0.2 3 None 4 None 5 None
我正在对一个 Pandas 系列进行相对繁重的应用。有什么方法可以返回一些打印反馈,说明每次调用函数时在函数内部进行打印还有多远? 最佳答案 您可以使用跟踪器包装您的函数。以下两个示例,一个基于完成的
我有一个 DataFrame,其中一列包含列表作为单元格内容,如下所示: import pandas as pd df = pd.DataFrame({ 'col_lists': [[1, 2
我想使用 Pandas df.apply 但仅限于某些行 作为一个例子,我想做这样的事情,但我的实际问题有点复杂: import pandas as pd import math z = pd.Dat
我有以下 Pandas 数据框 id dist ds 0 0 0 0 5 1 0 0 7 2 0 0
这发生在我尝试使用 Gradle 构建时。由于字符串是对象,因此似乎没有理由发生此错误: No signature of method: java.util.HashMap.getOrDefault(
您好,有人可以解释为什么在 remaining() 函数中的 Backbone 示例应用程序 ( http://backbonejs.org/examples/todos/index.html ) 中
我有两个域类:用户 class User { String username String password String email Date dateCreated
问题陈述: 一个 pandas dataframe 列系列,same_group 需要根据两个现有列 row 和 col 的值从 bool 值创建。如果两个值在字典 memberships 中具有相似
apporable 报告以下错误: error: unknown type name 'MKMapItem'; did you mean 'MKMapView'? MKMapItem* destina
我有一个带有地址列的大型 DataFrame: data addr 0 0.617964 IN,Krishnagiri,635115 1 0.635428 IN,Chennai
我有一个列表list,里面有这样的项目 ElementA: Number=1, Version=1 ElementB: Number=1, Version=2 ElementC: Number=1,
我正在编译我的源代码,它只是在没有运行应用程序的情况下终止。这是我得到的日志: Build/android-armeabi-debug/com.app4u.portaldorugby/PortalDo
我正在尝试根据另一个单元格的值更改单元格值(颜色“红色”或“绿色”)。我运行以下命令: df.loc[0, 'Colour'] = df.loc[0, 'Count'].apply(lambda x:
我想弄清楚如何使用 StateT结合两个 State基于对我的 Scalaz state monad examples 的评论的状态转换器回答。 看来我已经很接近了,但是在尝试申请 sequence
如果我已经为它绑定(bind)了集合,我该如何添加 RibbonLibrary 默认的快速访问项容器。当我从 UI 添加快速访问工具项时,它会抛出 Operation is not valid whi
在我学习期间Typoclassopedia我遇到了这个证明,但我不确定我的证明是否正确。问题是: One might imagine a variant of the interchange law
我是一名优秀的程序员,十分优秀!