Java 如何在使用Jackson和@JSonPOJOBuilder反序列化JSON时检索解析器上下文
问题是:是否有可能在不编写完整的自定义反序列化程序的情况下,使用POJO对象和/或POJOCreator(出于报告/调试目的)检索json解析器 让我在例子中解释一下。目前,我正在使用和mixin反序列化JSON:Java 如何在使用Jackson和@JSonPOJOBuilder反序列化JSON时检索解析器上下文,java,json,jackson,Java,Json,Jackson,问题是:是否有可能在不编写完整的自定义反序列化程序的情况下,使用POJO对象和/或POJOCreator(出于报告/调试目的)检索json解析器 让我在例子中解释一下。目前,我正在使用和mixin反序列化JSON: public interface Custom { ... } protected class CustomImpl implements Custom { CustomImpl(String prop1, Integer prop2,...) {} ... } @J
public interface Custom {
...
}
protected class CustomImpl implements Custom {
CustomImpl(String prop1, Integer prop2,...) {}
...
}
@JsonDeserialize(builder=CustomBuilder.class)
public abstract class CustomMixIn {
public CustomMixIn(
JsonProperty("prop1") String prop1,
JsonProperty("prop2") Integer prop2,
...
) {}
}
@JsonPOJOBuilder(buildMethodName="build")
public class CustomBuilder {
public String prop1;
public Integer prop2
...
public Custom build() {
// validate fields, perform other prerequisite actions
return new CustomImpl(prop1, prop2,...);
}
}
...
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Custom.class, CustomMixIn.class);
正如你可能看到的那样,一切都非常简单,而且它实际上是有效的。但是,我希望在CustomBuilder.build()方法中引用当前活动的解析器,以便能够正确报告所加载数据的问题/功能。抛出异常是不合适的,因为我想报告的不是错误,只是数据的“某些特定属性”。您可以覆盖标准的Jackson“builder”反序列化程序,并将json解析器实例注入到builder bean中。可以通过使用设置自定义反序列化器 但我不能说它看起来很优雅。这是因为不幸的是,
BuilderBasedDeserializer.finishBuild(…)
方法是final,这使得实际上不可能以示例中所示的其他方式注入json解析器。将其作为构造函数或构建方法参数传递看起来会更好
以下是一个例子:
public class JacksonBuilder {
public static final String JSON = "{\"field\":\"value\"}";
@JsonDeserialize(builder = Builder.class)
public static class Bean {
public final String field;
public Bean(String field) {
this.field = field;
}
@Override
public String toString() {
return "Bean{" +
"field='" + field + '\'' +
'}';
}
}
static interface JsonParserAware {
void withJsonParser(JsonParser parser);
}
static class Builder implements JsonParserAware {
public String field;
private JsonParser parser;
@Override
public void withJsonParser(JsonParser parser) {
this.parser = parser;
}
public Bean build() {
System.out.println(parser);
return new Bean(field + "(build by builder)");
}
}
private static class MyBuilderDeserializer extends BuilderBasedDeserializer {
protected MyBuilderDeserializer(BuilderBasedDeserializer src) {
super(src);
_vanillaProcessing = false;
}
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt) throws IOException {
Object object = super.deserializeFromObject(jp, ctxt);
if (object instanceof JsonParserAware) {
((JsonParserAware) object).withJsonParser(jp);
}
return object;
}
}
private static class BuilderBeanDeserializerModifier extends BeanDeserializerModifier {
@Override
public JsonDeserializer<?> modifyDeserializer(
DeserializationConfig config,
BeanDescription beanDesc,
JsonDeserializer<?> deserializer) {
if (deserializer instanceof BuilderBasedDeserializer) {
return new MyBuilderDeserializer((BuilderBasedDeserializer) deserializer);
}
return super.modifyDeserializer(config, beanDesc, deserializer);
}
}
public static void main(String[] args) throws IOException {
final SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BuilderBeanDeserializerModifier());
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.readValue(JSON, Bean.class));
}
}
谢谢你的食谱!这看起来很难,但似乎比我自己解决问题的所有努力都要好。我想知道为什么杰克逊的作者经常使用
final
。
Parser: com.fasterxml.jackson.core.json.ReaderBasedJsonParser@6be46e8f
Bean{field='value(build by builder)'}