用于枚举的自定义Xstream / JSON转换器

时间:2013-01-11 17:59:59

标签: java json enums xstream oxm

我有以下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以便获得所需的映射?提前谢谢!

3 个答案:

答案 0 :(得分:3)

你可以通过做两件事来做到这一点:

  1. 为您的枚举(toString())添加查找方法和MyStateEnum覆盖;和
  2. 扩展XStream的AbstractSingleValueConverter而非实施Converter
  3. 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),您现在可以通过提供desc字符串从外部查找所有各种枚举值。 MyStateEnumConverter(扩展AbstractSingleValueConverter)使用您的toString()覆盖,将MyStateEnum实例与文本字符串相关联。

    因此,当XStream解析JSON时,它会看到一个JSON对象,例如“打开”,这个新的转换器知道将“打开”传递给转换器的fromString(String)方法,后者又使用{{ 1}}查找相应的枚举实例。

    不要忘记在原始问题中显示的getMyStateByDesc(String)实例中注册您的转换器。

答案 1 :(得分:0)

您可以使用EnumToStringConverter

Documentation

实施例

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

...

使用xstream.autodetectAnnotations(true)

答案 2 :(得分:-2)

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

尝试例如Genson,它将开箱即用。 json流中的值将是“Close”,“Indeterminate”等,并且在反序列化时将生成正确的枚举。

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