java - (反)序列化枚举集

标签 java enums jackson enumset

是否有使用 Jackson 序列化和反序列化枚举集的简单方法?

private enum Type {
    YES, NO
}

@JacksonXmlProperty(localName = "type", isAttribute = true)
private final EnumSet<Type> types;

这给出了以下 XML:

...<type type="YES" type="NO"/>...

此 XML 无效,因为存在重复的属性。

我还尝试了以下注释:

@JsonSerialize(using = EnumSetSerializer.class)
@JacksonXmlProperty(localName = "type", isAttribute = true)
private final EnumSet<Type> mTypes;

但这会产生以下错误:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Class com.fasterxml.jackson.databind.ser.std.EnumSetSerializer has no default (no arg) constructor

最佳答案

在这种情况下,您应该编写一个自定义的 EnumSet 序列化器/反序列化器,将枚举集转换为字符串。这是一个完整的例子:

@SuppressWarnings({"unchecked", "raw"})
public class JacksonEnumSet {
    public enum Type {
        YES, NO
    }
    public static class Bean {
        @JacksonXmlElementWrapper(useWrapping = false)
        @JacksonXmlProperty(localName = "type", isAttribute = true)
        @JsonSerialize(using = EnumSetSerializer.class)
        @JsonDeserialize(using = EnumSetDeserializer.class)
        private final EnumSet<Type> types;

        @JsonCreator
        public Bean(@JsonProperty("type") final EnumSet<Type> types) {this.types = types;}

        public EnumSet<Type> getTypes() {return types;}

        @Override
        public String toString() {
            return "Bean{" +
                    "types=" + types +
                    '}';
        }
    }

    public static class EnumSetSerializer extends JsonSerializer<EnumSet> {

        @Override
        public void serialize(
                final EnumSet value,
                final JsonGenerator gen,
                final SerializerProvider serializers)
                throws IOException {
            final StringBuilder builder = new StringBuilder();
            for (final Object e : value) {
                if (builder.length() > 0) {
                    builder.append(";");
                }
                builder.append(e);
            }
            gen.writeString(builder.toString());
        }
    }

    public static class EnumSetDeserializer extends JsonDeserializer<EnumSet>
        implements ContextualDeserializer {
        private Class enumType;

        @Override
        public EnumSet deserialize(
                final JsonParser p,
                final DeserializationContext ctxt) throws IOException {
            final String string = p.getValueAsString();
            final EnumSet enumSet = EnumSet.noneOf(enumType);
            for (final String name : string.split(";")) {
                enumSet.add(Enum.valueOf(enumType, name));
            }
            return enumSet;
        }

        @Override
        public JsonDeserializer<?> createContextual(
                final DeserializationContext ctxt, final BeanProperty property)
                throws JsonMappingException {
            final CollectionLikeType type = (CollectionLikeType)property.getType();
            final EnumSetDeserializer enumSetDeserializer = new EnumSetDeserializer();
            enumSetDeserializer.enumType = type.getContentType().getRawClass();
            return enumSetDeserializer;
        }
    }

    public static void main(String[] args) throws IOException {
        final XmlMapper mapper = new XmlMapper();
        final Bean bean = new Bean(EnumSet.allOf(Type.class));
        final String xml = mapper.writeValueAsString(bean);
        System.out.println(xml);
        System.out.println(mapper.readValue(xml, Bean.class));
    }

}

输出:

<Bean xmlns="" type="YES;NO"></Bean>
Bean{types=[YES, NO]}

关于java - (反)序列化枚举集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30245851/

相关文章:

java - 运行tomcat时设置Java窗口的标题

java - Eclipse RCP 相互比较命令

c++ - 使用枚举实例化模板

c# - 返回枚举列表而不是枚举扩展帮助器中的字符串

spring - 使用 spring、jackson 格式化 LocalDateTime

Java VoIP 框架

java - Objectify 5 的多态性

java - 将字符串中的数字与枚举进行比较

java - jackson 自定义序列化 getter

java - MongoDB - 如何在 Java 中使用 printjson 输出