2

ジャクソンで列挙セットをシリアライズおよびデシリアライズする簡単な方法はありますか?

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
4

1 に答える 1

1

この場合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]}
于 2015-05-16T15:44:58.127 に答える