Java 如何在使用Jackson和@JSonPOJOBuilder反序列化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

问题是:是否有可能在不编写完整的自定义反序列化程序的情况下,使用POJO对象和/或POJOCreator(出于报告/调试目的)检索json解析器

让我在例子中解释一下。目前,我正在使用和mixin反序列化JSON:

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)'}