If jsonString
is generated by you, you can consider to add type info
and then use it to convert deserialized object. You could refer to this post for how to do it.
If jsonString
is generated by other services beyond your control, then there's no type info you can get so you can only try it one by one, @Sachin Gupta's answer would be a nice choice.
I'd like to provide an additional option: define an all-in-one
entity including all fields of MyClass1
, MyClass2
and MyClass3
, and make MyClass1
, MyClass2
and MyClass3
be separated wrapper and only expose related fields for each. Code as follows:
Class AllInOne
:
public class AllInOne {
protected String a;
protected String b;
protected String c;
public A asA() {
return new A(this);
}
public B asB() {
return new B(this);
}
public C asC() {
return new C(this);
}
}
Class A
:
public class A {
private AllInOne allInOne;
public A(AllInOne allInOne) {
this.allInOne = allInOne;
}
public String getA() {
return allInOne.a;
}
}
Class B
:
public class B {
private AllInOne allInOne;
public B(AllInOne allInOne) {
this.allInOne = allInOne;
}
public String getB() {
return allInOne.b;
}
}
Class C
:
public class C {
private AllInOne allInOne;
public C(AllInOne allInOne) {
this.allInOne = allInOne;
}
public String getC() {
return allInOne.c;
}
}
Test code:
public class Main {
public static void main(String[] args) throws IOException {
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
String jsonA = "{\"a\":\"a value\"}";
String jsonB = "{\"b\":\"b value\"}";
String jsonC = "{\"c\":\"c value\"}";
needTypeA(om.readValue(jsonA, AllInOne.class).asA());
needTypeB(om.readValue(jsonB, AllInOne.class).asB());
needTypeC(om.readValue(jsonC, AllInOne.class).asC());
}
private static void needTypeA(A a) {
System.out.println(a.getA());
}
private static void needTypeB(B b) {
System.out.println(b.getB());
}
private static void needTypeC(C c) {
System.out.println(c.getC());
}
}
With implementation like this, we erased the specific type info at deserialization step, and bring it back at the moment we really need/use it. And as you can see there's not too much extra code, because what we actually did is just moving all fields declaration together, and added couple methods.
Notes:
- I declare fields in
AllInOne
to be protected
, putting all POJO class in the same package will make A
, B
and C
be able to access them directly, but not for other classes outside.
- Setting
om.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
to make jackson deserialize by field
, so that we can remove duplicate setter
and getter
from AllInOne
class
- If you do need to know the type info, you could add methods like
isA
inside AllInOne
based on the fields info