假设我有以下POJO:
class Pojo {
String s;
Object o;
Map<String, String> m;
}
而且在运行时,我想要除一个属性外的所有属性的默认序列化/反序列化。通常,我要在序列化时用数据库中的字段ID替换字段,这与其他问题类似。
例如,我要替换o
为从外部映射获得的字符串(例如:object1
<=>“ 123”和object2
<=>“ 456”):
o
并替换(如果o
是object1
,则序列化为字符串“ 123”)o
back 的原始值(即object1
),并使用来重新创建Pojo
对象o = object1
。我知道模块是做到这一点的一种方法,但是我不确定如何使用它们,同时又为不需要更改的属性保留了自动BeanSerializer / Deserializer。
有人可以举一个例子(甚至是人为的)还是一种替代方法?
编辑
为了更清楚一点,我可以对Mixins进行以下操作:
ObjectMapper mapper = new ObjectMapper(MongoBsonFactory.createFactory());
mapper.addMixInAnnotations(Pojo.class, PojoMixIn.class);
ObjectReader reader = mapper.reader(Pojo.class);
DBEncoder dbEncoder = DefaultDBEncoder.FACTORY.create();
OutputBuffer buffer = new BasicOutputBuffer();
dbEncoder.writeObject(buffer, o);
使用以下Mixin:
abstract class PojoMixIn {
@JsonIgnore Object o;
}
然后将所需的字符串添加到JSON内容。但是我需要在编译时知道是该o
字段需要替换,而我不需要。
我认为@JsonSerialize
,@JsonDeserialize
这就是您所需要的。这些注释使您可以控制特定字段的序列化/反序列化。这个问题展示了将它们组合为一个注释的优雅方法。
UPD。
对于这种复杂的情况,您可以看一下BeanSerializerModifier/BeanDeserializerModifier
类。这个想法是BeanSerializer/BeanDeserializer
使用特定字段的自定义逻辑来修改常规,然后让基本实现来做其他事情。稍后再发布示例。
UPD2。 如我所见,一种方法可能是使用changeProperties
method并分配自己的序列化程序。
UPD3。 更新了自定义序列化程序的工作示例。反序列化可以类似的方式进行。
UPD 4。 更新了具有完全自定义序列化/反序列化的示例。(我用过 jakson-mapper-asl-1.9.8 )
public class TestBeanSerializationModifiers {
static final String PropertyName = "customProperty";
static final String CustomValue = "customValue";
static final String BaseValue = "baseValue";
// Custom serialization
static class CustomSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String customValue = CustomValue; // someService.getCustomValue(value);
jgen.writeString(customValue);
}
}
static class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); i++) {
BeanPropertyWriter beanPropertyWriter = beanProperties.get(i);
if (PropertyName.equals(beanPropertyWriter.getName())) {
beanProperties.set(i, beanPropertyWriter.withSerializer(new CustomSerializer()));
}
}
return beanProperties;
}
}
// Custom deserialization
static class CustomDeserializer extends JsonDeserializer<Object> {
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// serialized value, 'customValue'
String serializedValue = jp.getText();
String baseValue = BaseValue; // someService.restoreOldValue(serializedValue);
return baseValue;
}
}
static class MyBeanDeserializerModifier extends BeanDeserializerModifier {
@Override
public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) {
Iterator<SettableBeanProperty> beanPropertyIterator = builder.getProperties();
while (beanPropertyIterator.hasNext()) {
SettableBeanProperty settableBeanProperty = beanPropertyIterator.next();
if (PropertyName.equals(settableBeanProperty.getName())) {
SettableBeanProperty newSettableBeanProperty = settableBeanProperty.withValueDeserializer(new CustomDeserializer());
builder.addOrReplaceProperty(newSettableBeanProperty, true);
break;
}
}
return builder;
}
}
static class Model {
private String customProperty = BaseValue;
private String[] someArray = new String[]{"one", "two"};
public String getCustomProperty() {
return customProperty;
}
public void setCustomProperty(String customProperty) {
this.customProperty = customProperty;
}
public String[] getSomeArray() {
return someArray;
}
public void setSomeArray(String[] someArray) {
this.someArray = someArray;
}
}
public static void main(String[] args) {
SerializerFactory serializerFactory = BeanSerializerFactory
.instance
.withSerializerModifier(new MyBeanSerializerModifier());
DeserializerFactory deserializerFactory = BeanDeserializerFactory
.instance
.withDeserializerModifier(new MyBeanDeserializerModifier());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializerFactory(serializerFactory);
objectMapper.setDeserializerProvider(new StdDeserializerProvider(deserializerFactory));
try {
final String fileName = "test-serialization.json";
// Store, "customValue" -> json
objectMapper.writeValue(new File(fileName), new Model());
// Restore, "baseValue" -> model
Model model = objectMapper.readValue(new File(fileName), Model.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}
问题内容: 我已经创建了自己的文件,并通过将其设置为系统类加载器。它已经初始化,并且一切正常,但是找不到我要加载的类。这是: 我已确认该罐子存在,并且路径正确。这是我在程序中如何称呼它: 这是我得到的例外(第166行是指我尝试创建新行的行: 我什至尝试像这样显式加载类: 是什么原因造成的?它不应该“正常工作”吗? 更新: 这是来自的重要代码 更新2: 这是一个SSCCE:http : //nucl
问题内容: 我想将我的python软件包设为“ pip installable”。问题在于,程序包具有必须来自用户的初始Shell脚本(例如)的Shell脚本。 但是在安装之后,用户并不完全知道脚本的去向(大概是,但是我们不能保证)。当然,用户可以运行并手动编辑其初始化脚本。 但我想使这一步骤自动化。我可以创建一个新的distutils命令,但不调用它。而且我可以扩展,但是安装会通过pip中断(尽
除了可以在浏览器中通过URL调用一个 控制器 外,也可以通过命令行接口(CLI)调用。 什么是CLI? 为什么使用这种方式? 它如何工作? 什么是CLI? 命令行接口是一种基于文本的和计算机交互的方式。 如果想查看更详细说明,请看Wikipedia article. 为什么使用命令行? 虽然不是必须的,但在某些情况下我们会用到命令行 使用 cron 定时运行任务而不需要使用 wget 或 curl
除了从浏览器中通过 URL 来调用程序的 控制器 之外, 你也可以通过 CLI (命令行界面)的方式来调用。 目录 以 CLI 方式运行 什么是 CLI ? 为什么使用命令行? 让我们试一试:Hello World! 就这么简单! 什么是 CLI ? CLI (命令行界面)是一种基于文本的和计算机交互的方式。 更多信息, 请查看 维基百科 。 为什么使用命令行? 虽然不是很明显,但是有很多情况下我
(假设Magic是4个字节,Command是1个字节,Options是2个字节,Bodysize是4个字节,并且body本身的长度是可变的。)我如何在不使用任何第三方库的情况下解析它? 通常我会说,可以这样做来存储数据包数据: 问题是,我首先提供头信息,然后以一种笨拙的方式添加正文数据。包对象有一个在不完整状态下可以访问的时间点。 我是用C++开发的,对于通过套接字发送和接收数据,使用了boost
我试图在PySpark中运行一个自定义的HDFS阅读器类。这个类是用Java编写的,我需要从PySpark访问它,可以从shell访问,也可以使用spark-submit访问。 有人能帮忙吗?谢了。