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

Java 用于枚举的自定义Xstream/JSON转换器,java,json,enums,xstream,oxm,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;

我有以下
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;
    }
}
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();
    }
}
我正在尝试编写一个XStream,它将知道如何将JSON元素“
mystate
”映射回一个
mystate
实例

"someJson": {
    "object1": {
        "mystate": closed
    }
}
这将在其他对象(
someJson
object1
)中生成一个
MyState.Close
实例。我已经启动了
转换器
,但还没有走多远:

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

如何实现
marshal
unmarshal
以获得所需的映射?提前谢谢

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

例如,尝试一下,它将开箱即用。 json流中的值将是“Close”、“Undeterminate”等,反序列化时将生成正确的枚举

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

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

例如,尝试一下,它将开箱即用。 json流中的值将是“Close”、“Undeterminate”等,反序列化时将生成正确的枚举

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

您可以通过做两件事来实现这一点:

  • 将查找方法以及
    toString()
    覆盖添加到枚举(
    mystatenum
    );及
  • 扩展XStream的
    AbstractSingleValueConverter
    而不是实现
    Converter
  • mystatenum

    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;
        }
    }
    
    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对象,比如“opened”,这个新转换器知道将“opened”传递到转换器的
    fromString(String)
    方法中,该方法反过来使用
    getMyStateByDesc(String)
    来查找适当的枚举实例

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

    不要忘了向您的
    XStream
    实例注册转换器,正如您在原始问题中所示。

    您可以通过做两件事来完成这一点:

  • 将查找方法以及
    toString()
    覆盖添加到枚举(
    mystatenum
    );及
  • 扩展XStream的
    AbstractSingleValueConverter
    而不是实现
    Converter
  • mystatenum

    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;
        }
    }
    
    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对象,比如“opened”,这个新转换器知道将“opened”传递到转换器的
    fromString(String)
    方法中,该方法反过来使用
    getMyStateByDesc(String)
    来查找适当的枚举实例

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

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

    您可以使用EnumToString converter

    范例

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

    使用xstream.autodetectanotations(true)

    您可以使用EnumToStringConverter

    范例

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

    使用xstream.autodetectAnnotations(true)

    正确回答错误的问题-我只是对xstream感兴趣,谁的
    JettisonMappedXmlDriver
    非常适合JSON。正确回答错误的问题-我只对xstream感兴趣,谁的
    JettisonMappedXmlDriver
    非常适合JSON。