如何使用Jackson JSON注解反序列化带参数方法生成的对象?
如何用Jackson调用指定方法生成对象进行反序列化
当然可以做到!Jackson默认是通过构造方法、setter方法或者字段来完成反序列化,但我们可以通过几种灵活的方式来调用你指定的getBar方法生成Bar实例。下面给你两种常用的实现方案:
方案一:先解析JSON为参数对象,再调用目标方法
这种方式简单直接,适合快速实现。我们先把JSON里的参数解析成一个临时的参数对象,再用这个对象的属性去调用getBar方法。
步骤1:定义参数DTO类
创建一个和JSON字段对应的类,用来接收解析后的参数:
class Params { private int par1; private int par2; // 生成getter和setter方法(Jackson需要它们来完成反序列化) public int getPar1() { return par1; } public void setPar1(int par1) { this.par1 = par1; } public int getPar2() { return par2; } public void setPar2(int par2) { this.par2 = par2; } }
步骤2:修改main方法实现逻辑
先把JSON解析成Params对象,再调用getBar生成Bar:
class Foo { Bar getBar(int par1, int par2) { // 这里是你的原有逻辑,返回Bar实例 return new Bar(par1, par2); } public static void main(String[] args) throws IOException { String json = "{\"par1\":1,\"par2\":2}"; ObjectMapper mapper = new ObjectMapper(); // 1. 解析JSON为参数对象 Params params = mapper.readValue(json, Params.class); // 2. 创建Foo实例并调用getBar方法 Foo foo = new Foo(); Bar bar = foo.getBar(params.getPar1(), params.getPar2()); // 现在bar就是你需要的实例了 } }
方案二:自定义Jackson反序列化器
如果你希望直接把JSON解析成Bar对象,而不需要中间的参数类,可以自定义一个反序列化器,让Jackson在解析时直接调用getBar方法。
步骤1:编写自定义反序列化器
继承Jackson的StdDeserializer,在deserialize方法里解析JSON参数并调用getBar:
class BarDeserializer extends StdDeserializer<Bar> { private final Foo fooInstance; // 构造方法:传入Foo实例(如果你的getBar需要特定的Foo实例) public BarDeserializer(Foo fooInstance) { super(Bar.class); this.fooInstance = fooInstance; } // 无参构造:默认创建新的Foo实例(如果不需要特定实例的话) public BarDeserializer() { this(new Foo()); } @Override public Bar deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 解析JSON为JsonNode JsonNode node = p.getCodec().readTree(p); // 提取参数值 int par1 = node.get("par1").asInt(); int par2 = node.get("par2").asInt(); // 调用getBar方法生成Bar实例 return fooInstance.getBar(par1, par2); } }
步骤2:注册并使用反序列化器
有两种方式可以让Jackson使用这个反序列化器:
方式A:在Bar类上添加注解
直接在Bar类上标注使用我们的反序列化器:
@JsonDeserialize(using = BarDeserializer.class) class Bar { // 你的Bar类逻辑 private int value1; private int value2; public Bar(int value1, int value2) { this.value1 = value1; this.value2 = value2; } }
然后main方法里直接解析成Bar:
public static void main(String[] args) throws IOException { String json = "{\"par1\":1,\"par2\":2}"; ObjectMapper mapper = new ObjectMapper(); Bar bar = mapper.readValue(json, Bar.class); }
方式B:在ObjectMapper上注册反序列化器
如果不想修改Bar类,可以在ObjectMapper上手动注册我们的反序列化器:
public static void main(String[] args) throws IOException { String json = "{\"par1\":1,\"par2\":2}"; Foo foo = new Foo(); // 可以用你自己的Foo实例 ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 注册自定义反序列化器 module.addDeserializer(Bar.class, new BarDeserializer(foo)); mapper.registerModule(module); // 直接解析JSON为Bar Bar bar = mapper.readValue(json, Bar.class); }
注意事项
- 如果
getBar是静态方法,那么反序列化器里可以直接调用Foo.getBar(par1, par2),不需要持有Foo实例。 - 如果JSON字段名和你要提取的参数名不一致,可以用
node.get("your_json_field").asInt()来对应,或者使用Jackson的@JsonProperty注解来映射。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

