Java 如何整理和取消整理对象类型字段?

Java 如何整理和取消整理对象类型字段?,java,marshalling,xstream,unmarshalling,Java,Marshalling,Xstream,Unmarshalling,我有一个带有泛型方法的接口 public interface A { public void setValue(Object value); public Object getValue(); } 实现此接口但将值限制为某些特定枚举类的类(例如值为X、Y、Z): 对于编组和解编组,我编写了一个特定的转换器 为了我的编组 public boolean canConvert(Class clazz) { return A.class.isAssignableFrom(clazz

我有一个带有泛型方法的接口

public interface A {
  public void setValue(Object value);
  public Object getValue();
  }
实现此接口但将值限制为某些特定枚举类的类(例如值为X、Y、Z):

对于编组和解编组,我编写了一个特定的转换器 为了我的编组

public boolean canConvert(Class clazz) {
    return A.class.isAssignableFrom(clazz);
}

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
    ...
    A entry = (A) source;
    writer.startNode("value");
    context.convertAnother(entry.getValue());
    writer.endNode();
    ...
}
这将生成一个类B的实例

...
    <value>X</value>
...
我放置了
Object.class
,因为我不知道它包含哪种对象类型。我希望XStream能够添加一些关于这方面的信息

这会失败,因为
Object type=context.convertOther(extra,Object.class)
与“X”字符串一起工作,而不一定要生成MyEnum类型的对象,这是
extra.setValue(type)
所期望的

如何强制或添加信息,以便XStream知道它必须生成的对象类型?


感谢阅读这篇长篇文章…

默认情况下,如果XStream遇到一个对象,其类派生自XStream可以转换的类,它会将类名放入“class”属性中

如果您的转换器
canConvert()
Object.class
返回
true
,那么您实际上是在覆盖XStream的默认转换器,您有责任执行以前的操作。除非实现一种自己存储类型信息的方法,否则在XML中就不会有关于类的信息


要么放弃
A.class
/
对象.class
转换器(因为没有显示转换器,所以不确定您拥有什么),使转换器仅特定于具体类(
canConvert
仅对
B.class
返回true),或者至少通过为基本接口而不是一般的
对象制作转换器来限制损坏。类
转换器(
canConvert
a.class.isAssignableFrom(类)
)返回true)在这种情况下,由您决定如何在文件中存储有关具体类的类的信息。

我按照此处的建议,添加了一些有关值的类的信息,并使用此信息进行解组。我将发布我的工作解决方案,以供可能发现此问题的任何其他读者参考:

public static class ExtraSearchOptionConverter implements Converter {
    public boolean canConvert(Class type) {
        return ExtraSearchOption.class.isAssignableFrom(type);
    }
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        ExtraSearchOption entry = (ExtraSearchOption) source;
        ...
        if (entry.getValue() != null) {
            writer.startNode("value");
            writer.addAttribute("class", entry.getValue().getClass().getName());
            context.convertAnother(entry.getValue());
            writer.endNode();
        }
    }
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        ExtraSearchOption extra = new ExtraSearchOption();
        ...
        if (reader.hasMoreChildren()) {
            reader.moveDown();
            String className = reader.getAttribute("class");
            Class<?> valueClass = null;
            if (className != null) {
                try {
                    valueClass = Class.forName(className);
                    Object type = context.convertAnother(extra, valueClass);
                    extra.setValue(type);
                } catch (ClassNotFoundException ex) {
                    logger.error("While retrieving class for ExtraSearchOptions value", ex);
                    }
            }
            reader.moveUp();
        }

        return extra;
    }

}
公共静态类ExtraSearchOptionConverter实现转换器{
公共布尔canConvert(类类型){
返回ExtraSearchOption.class.isAssignableFrom(类型);
}
公共无效封送处理(对象源、HierarchycalStreamWriter编写器、封送上下文){
ExtraSearchOption条目=(ExtraSearchOption)源;
...
if(entry.getValue()!=null){
作者:startNode(“价值”);
writer.addAttribute(“类”,entry.getValue().getClass().getName());
convertOther(entry.getValue());
writer.endNode();
}
}
公共对象解组(HierarchycalStreamReader读取器,解组上下文){
ExtraSearchOption extra=新的ExtraSearchOption();
...
if(reader.hasMoreChildren()){
reader.moveDown();
字符串className=reader.getAttribute(“类”);
Class valueClass=null;
if(className!=null){
试一试{
valueClass=Class.forName(className);
对象类型=context.convertOther(额外,valueClass);
额外设置值(类型);
}捕获(ClassNotFoundException ex){
logger.error(“为ExtraSearchOptions值检索类时”,ex);
}
}
reader.moveUp();
}
额外返还;
}
}

请显示自定义转换器的
canConvert()
实现。这看起来应该是正常的。顺便说一下,欢迎来到Stack Overflow!一般来说,这里的做法是将答案仅限于回答问题,并直接对问题本身或相关答案发表评论。因为这篇文章确实包含了一个相关的答案,我将对其进行编辑,将其重新表述为一个答案(否则我建议删除它)。谢谢!:)(我假设您的解决方案是有效的;请确认这种情况,以便我知道编辑是好的。)Mod:请忽略预编辑标志。
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
  ...
  reader.moveDown();
  Object type = context.convertAnother(extra, Object.class);
  extra.setValue(type);
  reader.moveUp();
  ...
  return extra;
}
public static class ExtraSearchOptionConverter implements Converter {
    public boolean canConvert(Class type) {
        return ExtraSearchOption.class.isAssignableFrom(type);
    }
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        ExtraSearchOption entry = (ExtraSearchOption) source;
        ...
        if (entry.getValue() != null) {
            writer.startNode("value");
            writer.addAttribute("class", entry.getValue().getClass().getName());
            context.convertAnother(entry.getValue());
            writer.endNode();
        }
    }
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        ExtraSearchOption extra = new ExtraSearchOption();
        ...
        if (reader.hasMoreChildren()) {
            reader.moveDown();
            String className = reader.getAttribute("class");
            Class<?> valueClass = null;
            if (className != null) {
                try {
                    valueClass = Class.forName(className);
                    Object type = context.convertAnother(extra, valueClass);
                    extra.setValue(type);
                } catch (ClassNotFoundException ex) {
                    logger.error("While retrieving class for ExtraSearchOptions value", ex);
                    }
            }
            reader.moveUp();
        }

        return extra;
    }

}