[英]Deserializing transient fields with XStream 1.4.2
I've faced with a requirement to deserialize fields that possibly can be transient using XStream 1.4.2. 我已经面临着反序列化使用XStream 1.4.2可能是瞬态的字段的要求。 Despite of that, such fields may be annotated with both @XStreamAlias
and @XStreamAsAttribute
. 尽管如此,可以使用@XStreamAlias
和@XStreamAsAttribute
注释此类字段。 Yes, I know, it sounds weird, and this is an indicator of bad design, but this is what I currently have. 是的,我知道,这听起来很奇怪,这表明设计不良,但这就是我目前所拥有的。 Since XStream offers a way to specify custom converter, I tried to extend com.thoughtworks.xstream.converters.reflection.ReflectionConverter
in order to override the default way of omitting all transient fields trying to make XStream allow to deserialize them. 由于XStream提供了一种指定自定义转换器的方法,因此我尝试扩展com.thoughtworks.xstream.converters.reflection.ReflectionConverter
,以覆盖忽略所有试图使XStream对其反序列化的所有临时字段的默认方式。 However, I've fully stuck having two ideas to implement such a converter, but none of them works. 但是,我完全没有两个想法来实现这样的转换器,但是它们都没有用。 So here is what I tried: 所以这是我尝试的:
The 1st way doesn't work: 第一种方法不起作用:
public final class TransientSimpleConverter extends ReflectionConverter {
private final Class<?> type;
private TransientSimpleConverter(Class<?> type, Mapper mapper, ReflectionProvider reflectionProvider) {
super(mapper, reflectionProvider);
this.type = type;
}
public static TransientSimpleConverter transientSimpleConverter(Class<?> type, XStream xStream) {
return new TransientSimpleConverter(type, xStream.getMapper(), xStream.getReflectionProvider());
}
@Override
protected boolean shouldUnmarshalTransientFields() {
return true;
}
@Override
public boolean canConvert(Class type) {
return this.type == type;
}
}
The 2nd way doesn't work either: 第二种方法也不起作用:
public final class TransientComplexConverter extends ReflectionConverter {
private final Class<?> type;
private TransientComplexConverter(Class<?> type, Mapper mapper, ReflectionProvider provider) {
super(mapper, provider);
this.type = type;
}
public static TransientComplexConverter transientComplexConverter(Class<?> type, Mapper mapper, Iterable<String> fieldNames) {
return new TransientComplexConverter(type, mapper, TransientHackReflectionProvider.transientHackReflectionProvider(type, fieldNames));
}
@Override
public boolean canConvert(Class type) {
return this.type == type;
}
private static final class TransientHackReflectionProvider extends PureJavaReflectionProvider {
private final Class<?> type;
private final Collection<Field> allowedFields;
private final Collection<String> allowedAliases;
private TransientHackReflectionProvider(Class<?> type, Collection<Field> allowedFields, Collection<String> allowedAliases) {
this.type = type;
this.allowedFields = allowedFields;
this.allowedAliases = allowedAliases;
}
public static TransientHackReflectionProvider transientHackReflectionProvider(final Class<?> type, Iterable<String> fieldNames) {
final Collection<Field> allowedFields = from(fieldNames).transform(new Function<String, Field>() {
@Override
public Field apply(String name) {
return field(type, name);
}
}).toList();
final Collection<String> allowedAliases = transform(allowedFields, new Function<Field, String>() {
@Override
public String apply(Field f) {
return f.getName();
}
});
return new TransientHackReflectionProvider(type, allowedFields, allowedAliases);
}
@Override
protected boolean fieldModifiersSupported(Field field) {
return allowedFields.contains(field) ? true : super.fieldModifiersSupported(field);
}
@Override
public boolean fieldDefinedInClass(String fieldName, Class type) {
return type == this.type && allowedAliases.contains(fieldName) ? true : super.fieldDefinedInClass(fieldName, type);
}
private static final Field field(Class<?> type, String name) {
try {
final Field field = type.getDeclaredField(name);
checkArgument(isTransient(field.getModifiers()), name + " is not transient");
checkArgument(field.getAnnotation(XStreamAsAttribute.class) != null, name + " must be annotated with XStreamAsAttribute");
checkArgument(field.getAnnotation(XStreamAlias.class) != null, name + " must be annotated with XStreamAlias");
return field;
} catch (final SecurityException ex) {
throw new RuntimeException(ex);
} catch (final NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
}
}
Any suggestions or ideas for a workaround? 有任何解决方法的建议或想法吗? Thanks in advance. 提前致谢。
I know this post is old, but maybe someone is still interested. 我知道这篇文章很旧,但也许有人仍然对此感兴趣。 My solution: 我的解决方案:
XStream xstream = new XStream(new MyPureJavaReflectionProvider());
class MyPureJavaReflectionProvider extends PureJavaReflectionProvider {
public MyPureJavaReflectionProvider() {
this(new FieldDictionary(new ImmutableFieldKeySorter()));
}
public MyPureJavaReflectionProvider(FieldDictionary fieldDictionary) {
super(fieldDictionary);
}
protected boolean fieldModifiersSupported(Field field) {
int modifiers = field.getModifiers();
return !Modifier.isStatic(modifiers);
}
public boolean fieldDefinedInClass(String fieldName, Class type) {
Field field = fieldDictionary.fieldOrNull(type, fieldName, null);
return field != null && fieldModifiersSupported(field);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.