1

我有以下内容Enum

public enum MyState {
    Open("opened"),
    Close("closed"),
    Indeterminate("unknown");

    private String desc;

    private MyState(String desc) {
        setDesc(desc);
    }

    public String getDesc() {
        return this.desc;
    }

    private void setDesc(String desc) {
        this.desc = desc;
    }
}

我正在尝试编写一个 XStream Converter,它知道将 JSON 元素“ mystate”映射回一个MyState实例。

"someJson": {
    "object1": {
        "mystate": closed
    }
}

除了其他对象(someJsonobject1)之外,这应该产生一个MyState.Close实例。我已经开始了Converter,但还没有走得很远:

public class MyStateEnumConverter implement Converter {
    @Override
    public boolean canConvert(Class clazz) {
        return clazz.equals(MyState.class);
    }

    @Override
    public void marshal(Object value, HierarchialStreamWriter writer, MarshallingContext context) {
        ??? - no clue here
    }

    @Override
    public Object unmarshal(HierarchialStreamReader reader, UnmarshallingContext context) {
        ??? - no clue here
    }
}

然后,创建映射器并使用它:

XStream mapper = new XStream(new JettisonMappedXmlDriver());
mapper.registerConverter(new MyStateEnumConverter);

SomeJson jsonObj = mapper.fromXML(jsonString);

// Should print "closed"
System.out.println(jsonObject.getObject1().getMyState().getDesc());

如何实现marshalunmarshal获得所需的映射?提前致谢!

4

3 回答 3

3

您可以通过做 2 件事来完成此操作:

  1. 添加一个查找方法以及一个toString()覆盖到你的枚举(MyStateEnum);和
  2. 扩展 XStreamAbstractSingleValueConverter而不是实现Converter

MyStateEnum

public enum MyStateEnum {
    // Everything you had is fine

    // But now, add:
    public static MyStateEnum getMyStateByDesc(String desc) {
        for(MyStateEnum myState : MyStateEnum.values())
            if(myState.getDesc().equals(desc))
                return myState;

        return null;
    }

    @Override
    public String toString() {
        return getDesc();
    }
}

MyStateEnumConverter

public class MyStateEnumConverter extends AbstractSingleValueConverter {
    @Override
    public boolean canConvert(Class clazz) {
        return clazz.equals(MyStateEnum.class);
    }

    @Override
    public Object fromString(String parsedText) {
        return MyStateEnum.getMyStateByDesc(parsedText);
    }
}

通过添加到枚举中,您现在可以通过提供字符串getMyStateByDesc(String)来从外部查找所有各种枚举值。(which extends )desc在后台使用您的覆盖将实例与文本字符串相关联。MyStateEnumConverterAbstractSingleValueConvertertoString()MyStateEnum

因此,当 XStream 解析 JSON 时,它会看到一个 JSON 对象,比如“opened”,并且这个新转换器知道将“opened”传递给转换器的fromString(String)方法,该方法反过来用于getMyStateByDesc(String)查找适当的枚举实例。

不要忘记在您的XStream实例中注册您的转换器,正如您在原始问题中已经显示的那样。

于 2013-01-23T16:44:34.543 回答
0

您可以使用 EnumToStringConverter

文档

例子

@XStreamConverter(EnumToStringConverter.class)
public enum MyStateEnum {
enter code here

...

使用 xstream.autodetectAnnotations(true)

于 2014-05-21T14:31:07.837 回答
-2

为什么要使用 xstream 来支持 json?您有几个其他专门用于 json 的库,并且做得很好。不带引号也关闭是无效的 json。

尝试例如Genson,它会开箱即用。json 流中的值将是“关闭”、“不确定”等,并且在反序列化时会产生正确的枚举。

class SomeObject {
   private MyState state;
   ...
}

Genson genson = new Genson();
// json = {"state" : "Indeterminate"}
String json = genson.serialize(new SomeObject(MyState.Indeterminate));

// deserialize back
SomeObject someObject = genson.deserialize(json, SomeObject.class);

// will print unknown
System.out.println(someObject.getDesc());
于 2013-01-11T18:42:16.873 回答