gpt4 book ai didi

java - 处理 Jackson 序列化的常见方法是什么

转载 作者:行者123 更新时间:2023-12-01 14:11:25 25 4
gpt4 key购买 nike

目前我有一个项目,使用 Spring-Hibernate 和 Jackson 来处理 JSON。第一次尝试使用 Jackson 时,我总是遇到 LazyInitializationException,有时还会遇到互相引用的多个实体的无限循环。然后我找到了 @JsonIgnore@JsonIdentityInfo

现在的问题是有时需要忽略属性,但有时我只需要这些属性可序列化。有没有办法有时忽略多个字段,有时在运行时序列化字段?

我找到了“Serialization and Deserialization with Jackson: how to programmatically ignore fields?

但是如果我总是必须在注释中使用混合,如果一个对象有几十个属性要检索,那就很麻烦了。例如。在第1页中,我需要propertyApropertyBpropertyC;在第2页中我需要propertyApropertyC;在第3页中我只需要propertyB。仅在这些情况下,我就必须为每个页面创建 1 个类,从而产生 3 个类。

那么在这种情况下,有没有一种方法可以定义类似的内容:

objectA.ignoreAllExcept('propertyA');
String[] properties = {'propertyA', 'propertyC'};
objectB.ignoreAllExcept(properties); // Retrieve propertyA and propertyC
objectC.ignore(properties);

最佳答案

您可能正在寻找的是 Module 。文档说 Modules

Simple interface for extensions that can be registered with ObjectMappers to provide a well-defined set of extensions to default functionality.

以下是您如何使用它们来完成您想要的任务的示例。请注意,还有其他方法可以实现此目的;这只是其中之一。

一个简单的 DTO,可用于指定要过滤的属性:

public class PropertyFilter {

public Class<?> classToFilter;
public Set<String> propertiesToIgnore = Collections.emptySet();

public PropertyFilter(Class<?> classToFilter, Set<String> propertiesToIgnore) {
this.classToFilter = classToFilter;
this.propertiesToIgnore = propertiesToIgnore;
}
}

一个自定义模块,可根据您存储在当前请求中的某些属性过滤出属性。

public class MyModule extends Module {

@Override
public String getModuleName() {
return "Test Module";
}

@Override
public void setupModule(SetupContext context) {
context.addBeanSerializerModifier(new MySerializerModifier());
}

@Override
public Version version() {
// Modify if you need to.
return Version.unknownVersion();
}

public static class MySerializerModifier extends BeanSerializerModifier {

public BeanSerializerBuilder updateBuilder(SerializationConfig config,
BeanDescription beanDesc,
BeanSerializerBuilder builder) {
List<PropertyFilter> filters = (List<PropertyFilter>) RequestContextHolder.getRequestAttributes().getAttribute("filters", RequestAttributes.SCOPE_REQUEST);
PropertyFilter filter = getPropertyFilterForClass(filters, beanDesc.getBeanClass());
if(filter == null) {
return builder;
}

List<BeanPropertyWriter> propsToWrite = new ArrayList<BeanPropertyWriter>();
for(BeanPropertyWriter writer : builder.getProperties()) {
if(!filter.propertiesToIgnore.contains(writer.getName())) {
propsToWrite.add(writer);
}
}
builder.setProperties(propsToWrite);
return builder;
}


private PropertyFilter getPropertyFilterForClass(List<PropertyFilter> filters, Class<?> classToCheck) {
for(PropertyFilter f : filters) {
if(f.classToFilter.equals(classToCheck)) {
return f;
}
}
return null;
}
}

}

注意:BeanSerializerModifier中有一个changeProperties方法更适合更改属性列表的类(根据文档)。因此,您可以将 updateBuilder 中编写的代码移动到 changeProperties 方法中并进行适当的更改。

现在,您需要使用您的 ObjectMapper 注册此自定义模块 。您可以从应用程序上下文中获取 Jackson HTTP 消息转换器,并获取其对象映射器。我假设您已经知道如何做到这一点,因为您也一直在处理延迟初始化问题。

// Figure out a way to get the ObjectMapper.
MappingJackson2HttpMessageConverter converter = ... // get the jackson-mapper;
converter.getObjectMapper().registerModule(new MyModule())

你就完成了。当您想要自定义特定类型对象的序列化时,请为其创建一个 PropertyFilter ,将其放入 List 中,并使其在当前请求中作为属性使用。这只是一个简单的例子。您可能需要对其进行一些调整以满足您的需求。

在您的问题中,您似乎正在寻找一种方法来指定序列化对象本身的要过滤的属性。在我看来,应该避免这种情况,因为要过滤的属性列表不属于您的实体。但是,如果您确实想这样做,请创建一个为属性列表提供 settersgetters接口(interface)。假设接口(interface)的名称为 CustomSerialized 那么,您可以修改 MyModule 类来查找此 CustomSerialized 接口(interface)的实例并过滤掉相应的属性。

注意:您可能需要根据您正在使用的库的版本来调整/微调一些内容。

关于java - 处理 Jackson 序列化的常见方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18504733/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com