java Jackson Mapper 后构造
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6834677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson Mapper post-construct
提问by Brandon Yarbrough
I am using the Hymanson ObjectMapper
to deserialize some JSON into a Java class, which we'll call PlayerData
. I would like to add a bit of logic to the PlayerData
class to fix up some data after the fields have been loaded in. For example, some early JSON files used to use a "sex" flag instead of a "gender" falg, so if the sex flag is set but the gender flag is not set, I'd like to set the value of the gender field to be the value of the sex field.
我正在使用 HymansonObjectMapper
将一些 JSON 反序列化为一个 Java 类,我们称之为PlayerData
. 我想在类中添加一些逻辑以在PlayerData
加载字段后修复一些数据。例如,一些早期的 JSON 文件曾经使用“sex”标志而不是“gender”标志,所以如果设置了性别标志但未设置性别标志,我想将性别字段的值设置为性别字段的值。
Is there some sort of @PostConstruct or @AfterLoad annotation that I could affix to a method? Or perhaps an interface that I could implement? I didn't notice one in the documentation, but it seemed like an obvious feature.
是否有某种 @PostConstruct 或 @AfterLoad 注释可以附加到方法上?或者也许是我可以实现的接口?我没有注意到文档中的一个,但这似乎是一个明显的功能。
回答by Mike Rylander
Found this thru a linkin the comments (credit: fedor.belov). This appears to allow you to run code post construct.
通过评论中的链接找到了这个(来源:fedor.belov)。这似乎允许您运行代码后期构造。
Adding a comment for people who end up here via http://jira.codehaus.org/browse/HymanSON-645or http://jira.codehaus.org/browse/HymanSON-538and are looking for a method which is called after a deserializer completes. I was able to achieve the desired effect by including an annotation and writing a converter which uses the same class as input and output.
为通过http://jira.codehaus.org/browse/HymanSON-645或 http://jira.codehaus.org/browse/HymanSON-538来到这里并正在寻找一种称为方法的人添加评论 解串器完成后。我能够通过包含注释并编写一个转换器来实现预期的效果,该转换器使用与输入和输出相同的类。
@JsonDeserialize(converter=MyClassSanitizer.class) // invoked after class is fully deserialized
public class MyClass {
public String field1;
}
import com.fasterxml.Hymanson.databind.util.StdConverter;
public class MyClassSanitizer extends StdConverter<MyClass,MyClass> {
@Override
public MyClass convert(MyClass var1) {
var1.field1 = munge(var1.field1);
return var1;
}
}
回答by KARASZI István
If you're not using the @JsonCreator
, then Hymanson will use the setter and getter methods to set the fields.
如果您不使用@JsonCreator
,那么 Hymanson 将使用 setter 和 getter 方法来设置字段。
So if you define the following methods assuming that you have Sex
and Gender
enums:
因此,如果您定义以下方法,假设您拥有Sex
和Gender
枚举:
@JsonProperty("sex")
public void setSex(final Sex sex) {
this.sex = sex;
if (gender == null) {
gender = (sex == Sex.WOMAN) ? Gender.WOMAN : Gender.MAN;
}
}
@JsonProperty("gender")
public void setGender(final Gender gender) {
this.gender = gender;
if (sex == null) {
sex = (gender == Gender.WOMAN) ? Sex.WOMAN : Sex.MAN;
}
}
it would work.
它会工作。
Update: You can find all of the annotations of Hymanson library here.
更新:您可以在此处找到 Hymanson 库的所有注释。
Update2: Other solution:
更新2:其他解决方案:
class Example {
private final Sex sex;
private final Gender gender;
@JsonCreator
public Example(@JsonProperty("sex") final Sex sex) {
super();
this.sex = sex;
this.gender = getGenderBySex(sex)
}
@JsonFactory
public static Example createExample(@JsonProperty("gender") final Gender gender) {
return new Example(getSexByGender(gender));
}
private static Sex getSexByGender(final Gender) {
return (gender == Gender.WOMAN) ? Sex.WOMAN : Sex.MAN;
}
private static Gender getGenderBySex(final Sex) {
return (sex == Sex.WOMAN) ? Gender.WOMAN : Gender.MAN;
}
}
回答by StaxMan
This is something that has actually been suggested couple of times earlier. So maybe filing an RFE would make sense; there are multiple ways in which this could work: obvious ones being ability to annotate type (@JsonPostProcess(Processor.class)) and ability to register post-processor through Module API (so that there's basically a callback when Hymanson constructs deserializer, to let module specify post-processor to use if any). But perhaps there are even better ways to do this.
这实际上已经在早些时候提出了几次。所以也许提交 RFE 是有意义的;有多种方法可以工作:明显的是能够注释类型(@JsonPostProcess(Processor.class))和能够通过模块API注册后处理器(这样当Hymanson构造反序列化器时基本上有一个回调,让模块指定要使用的后处理器(如果有)。但也许有更好的方法来做到这一点。
回答by oberlies
This is not supported out of the box, but you can easily create your @JsonPostDeserialize
annotation for methods to be called after deserialization.
这不是开箱即用的,但您可以轻松地@JsonPostDeserialize
为反序列化后要调用的方法创建注释。
First, define the annotation:
首先,定义注解:
/**
* Annotation for methods to be called directly after deserialization of the object.
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonPostDeserialize {
}
Then, add the following registration and implementation code to your project:
然后,将以下注册和实现代码添加到您的项目中:
public static void addPostDeserializeSupport(ObjectMapper objectMapper) {
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDescription,
JsonDeserializer<?> originalDeserializer) {
return new CustomAnnotationsDeserializer(originalDeserializer, beanDescription);
}
});
objectMapper.registerModule(module);
}
/**
* Class implementing the functionality of the {@link JsonPostDeserialize} annotation.
*/
public class CustomAnnotationsDeserializer extends DelegatingDeserializer {
private final BeanDescription beanDescription;
public CustomAnnotationsDeserializer(JsonDeserializer<?> delegate, BeanDescription beanDescription) {
super(delegate);
this.beanDescription = beanDescription;
}
@Override
protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegatee) {
return new CustomAnnotationsDeserializer(newDelegatee, beanDescription);
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Object deserializedObject = super.deserialize(p, ctxt);
callPostDeserializeMethods(deserializedObject);
return deserializedObject;
}
private void callPostDeserializeMethods(Object deserializedObject) {
for (AnnotatedMethod method : beanDescription.getClassInfo().memberMethods()) {
if (method.hasAnnotation(JsonPostDeserialize.class)) {
try {
method.callOn(deserializedObject);
} catch (Exception e) {
throw new RuntimeException("Failed to call @JsonPostDeserialize annotated method in class "
+ beanDescription.getClassInfo().getName(), e);
}
}
}
}
}
Finally, modify your ObjectMapper
instance with addPostDeserializeSupport
, it will invoke all @JsonPostDeserialize
annotated method of deserialized objects.
最后,使用 修改您的ObjectMapper
实例addPostDeserializeSupport
,它将调用@JsonPostDeserialize
反序列化对象的所有带注释的方法。