【问题标题】:Deserializing transient fields with XStream 1.4.2使用 XStream 1.4.2 反序列化瞬态字段
【发布时间】:2014-02-21 08:23:43
【问题描述】:

我遇到了使用 XStream 1.4.2 反序列化可能是瞬态的字段的要求。尽管如此,这些字段可能会同时使用@XStreamAlias@XStreamAsAttribute 进行注释。是的,我知道,这听起来很奇怪,这表明设计不好,但这是我目前所拥有的。由于 XStream 提供了一种指定自定义转换器的方法,因此我尝试扩展 com.thoughtworks.xstream.converters.reflection.ReflectionConverter 以覆盖忽略所有瞬态字段的默认方法,以使 XStream 允许反序列化它们。但是,我完全坚持有两个想法来实现这样的转换器,但它们都不起作用。所以这是我尝试过的:

第一种方法不起作用:

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;
    }

}

第二种方式也不行:

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

    }

}

对于解决方法有什么建议或想法吗?提前致谢。

【问题讨论】:

    标签: java xml-serialization xstream xml-deserialization transient


    【解决方案1】:

    我知道这篇文章很旧,但也许有人仍然感兴趣。我的解决方案:

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

    【讨论】:

    • 自从我不再从事那个奇怪的项目以来已经快 3 年了,很遗憾无法检查您的解决方案,但感谢您的输入,无论如何,您是第一个回答它的人。
    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2015-04-18
    • 1970-01-01
    • 2015-10-18
    相关资源
    最近更新 更多