我有一个类层次结构,如下所示:
interface MyEntity {
...
}
class MyEntityRef {
String id;
...
}
class MyEntityImpl {
String id;
String name;
...
}
我想序列化为MyEntityRef
纯字符串的实例:
"someEntityId"
和MyEntityImpl
作为常规对象的实例:
{
id: "someEntityId",
name: "someName"
}
然后是另一种方法:当反MyEntity
序列化a时,MyEntityRef
如果json是纯字符串,我希望将其反序列化为a ,MyEntityImpl
如果它是常规json对象,则将其反序列化为a 。
在我实际的代码我有很多类型的实体(即多X
/ XRef
/XImpl
三元组)。为了避免列出所有这些内容,我对接口进行了如下注释:
@MyEntityAnnotation(ref=MyEntityRef.class, impl=MyEntityImpl.class)
interface MyEntity {
...
}
凡是指出基于该注释信息为所有实体解决上述序列化/反序列化方法的人,都应格外注意。
我尝试过的:我能想到的一切(SimpleDeserializers
/ SimpleSerializers
,BeanDeserializerModifier
/ BeanSerializerModifier
,TypeSerializer
/ TypeDeserializer
)
通过使用自定义反序列化器(请参见下文),从技术上讲这是可能的,但由于使用了反射和类型不安全的转换,因此似乎相当复杂且有些笨拙。使用双向引用可能会带来更好的运气,但这可能需要更改模型。
这是一个基于自定义反序列化器的示例:
public class JacksonEntity {
@Retention(RetentionPolicy.RUNTIME)
static public @interface MyAnnotation {
Class<?> ref();
Class<?> impl();
}
@MyAnnotation(ref = MyEntityRef.class, impl = MyEntityImpl.class)
static public interface MyEntity {
}
static public class MyEntityRef implements MyEntity {
private final String id;
public MyEntityRef(String id) {
this.id = id;
}
@JsonValue
public String getId() {
return id;
}
@Override
public String toString() {
return "MyEntityRef{" +
"id='" + id + '\'' +
'}';
}
}
static public class MyEntityImpl implements MyEntity {
public final String id;
public final String name;
@JsonCreator
public MyEntityImpl(@JsonProperty("id") String id, @JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "MyEntityImpl{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
static public class MyDeserializer extends JsonDeserializer<Object> {
private final Class<?> refType;
private final Class<?> implType;
public MyDeserializer(MyAnnotation annotation) {
this.refType = annotation.ref();
this.implType = annotation.impl();
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
JsonToken jsonToken = jp.getCurrentToken();
if (jsonToken == JsonToken.START_OBJECT) {
return jp.readValueAs(implType);
} else if (jsonToken == JsonToken.VALUE_STRING) {
try {
return refType.getConstructor(String.class).newInstance(jp.getValueAsString());
} catch (Exception e) {
throw new UnsupportedOperationException();
}
}
return null;
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
BeanDescription beanDesc,
JsonDeserializer<?> deserializer) {
MyAnnotation myAnnotation = beanDesc.getClassAnnotations().get(MyAnnotation.class);
// it must be interface, otherwise getting meeting recursion
if (myAnnotation != null && beanDesc.getBeanClass().isInterface()) {
return new MyDeserializer(myAnnotation);
}
return super.modifyDeserializer(config, beanDesc, deserializer);
}
});
mapper.registerModule(module);
MyEntityRef ref = new MyEntityRef("id1");
MyEntityImpl impl = new MyEntityImpl("id2", "value");
String jsonRef = mapper.writeValueAsString(ref);
System.out.println(jsonRef);
String jsonImpl = mapper.writeValueAsString(impl);
System.out.println(jsonImpl);
System.out.println(mapper.readValue(jsonRef, MyEntity.class));
System.out.println(mapper.readValue(jsonImpl, MyEntity.class));
}
}
输出:
"id1"
{"id":"id2","name":"value"}
MyEntityRef{id='id1'}
MyEntityImpl{id='id2', name='value'}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句