/** * Method that needs to be used instead of {@link #constructUsingToString} * if static type of enum is not known. * * @since 2.8 */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls, AnnotationIntrospector ai) { // oh so wrong... not much that can be done tho Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls; return constructUsingToString(enumCls, ai); }
EnumResolver r = EnumResolver.constructUsingToString((Class<Enum<?>>) to, null); T value = (T) r.findEnum((String) from); if (value == null) { throw new RuntimeException("Invalid value '" + from + "' for enum " + to);
/** * Factory method for constructing resolver that maps from Enum.toString() into * Enum value * * @since 2.8 */ public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls, AnnotationIntrospector ai) { Enum<?>[] enumValues = enumCls.getEnumConstants(); HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>(); // from last to first, so that in case of duplicate values, first wins for (int i = enumValues.length; --i >= 0; ) { Enum<?> e = enumValues[i]; map.put(e.toString(), e); } Enum<?> defaultEnum = (ai == null) ? null : ai.findDefaultEnumValue(enumCls); return new EnumResolver(enumCls, enumValues, map, defaultEnum); }
/** * @since 2.9 */ public EnumDeserializer(EnumResolver byNameResolver, Boolean caseInsensitive) { super(byNameResolver.getEnumClass()); _lookupByName = byNameResolver.constructLookup(); _enumsByIndex = byNameResolver.getRawEnums(); _enumDefaultValue = byNameResolver.getDefaultValue(); _caseInsensitive = caseInsensitive; }
protected EnumKD(EnumResolver er, AnnotatedMethod factory) { super(-1, er.getEnumClass()); _byNameResolver = er; _factory = factory; _enumDefaultValue = er.getDefaultValue(); }
private EnumResolver _getToStringResolver(DeserializationContext ctxt) { EnumResolver res = _byToStringResolver; if (res == null) { synchronized (this) { res = EnumResolver.constructUnsafeUsingToString(_byNameResolver.getEnumClass(), ctxt.getAnnotationIntrospector()); _byToStringResolver = res; } } return res; } }
@Override public Enum<?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonToken curr = jp.getCurrentToken(); // Usually should just get string value: if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) { String name = jp.getText(); Enum<?> result = _resolver.findEnum(name); if (result == null) { return _deserializeAltString(jp, ctxt, name); } return result; } // But let's consider int acceptable as well (if within ordinal range) if (curr == JsonToken.VALUE_NUMBER_INT) { // ... unless told not to do that. :-) (as per [JACKSON-412] _checkFailOnNumber(ctxt); int index = jp.getIntValue(); Enum<?> result = _resolver.getEnum(index); if (result == null && !ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdNumberException(Integer.valueOf(index), _resolver.getEnumClass(), "index value outside legal index range [0.."+_resolver.lastValidIndex()+"]"); } return result; } return _deserializeOther(jp, ctxt); }
protected EnumResolver<?> constructEnumResolver(Class<?> enumClass, DeserializationConfig config, AnnotatedMethod jsonValueMethod) { if (jsonValueMethod != null) { Method accessor = jsonValueMethod.getAnnotated(); if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(accessor); } return EnumResolver.constructUnsafeUsingMethod(enumClass, accessor); } // [JACKSON-212]: may need to use Enum.toString() if (config.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING)) { return EnumResolver.constructUnsafeUsingToString(enumClass); } return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector()); }
protected EnumResolver constructEnumResolver(Class<?> enumClass, DeserializationConfig config, AnnotatedMember jsonValueAccessor) { if (jsonValueAccessor != null) { if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(jsonValueAccessor.getMember(), config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } return EnumResolver.constructUnsafeUsingMethod(enumClass, jsonValueAccessor, config.getAnnotationIntrospector()); } // 14-Mar-2016, tatu: We used to check `DeserializationFeature.READ_ENUMS_USING_TO_STRING` // here, but that won't do: it must be dynamically changeable... return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector()); }
@Override public Object _parse(String key, DeserializationContext ctxt) throws IOException { if (_factory != null) { try { return _factory.call1(key); } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e); } } EnumResolver res = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING) ? _getToStringResolver(ctxt) : _byNameResolver; Enum<?> e = res.findEnum(key); if (e == null) { if ((_enumDefaultValue != null) && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) { e = _enumDefaultValue; } else if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { return ctxt.handleWeirdKey(_keyClass, key, "not one of values excepted for Enum class: %s", res.getEnumIds()); } // fall-through if problems are collected, not immediately thrown } return e; }
/** * Method used when actual String serialization is indicated using @JsonValue * on a method. * * @since 2.9 */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls, AnnotatedMember accessor, AnnotationIntrospector ai) { // wrong as ever but: Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls; return constructUsingMethod(enumCls, accessor, ai); }
/** * This method is needed because of the dynamic nature of constructing Enum * resolvers. */ @SuppressWarnings({ "unchecked" }) public static EnumResolver constructUnsafe(Class<?> rawEnumCls, AnnotationIntrospector ai) { /* This is oh so wrong... but at least ugliness is mostly hidden in just * this one place. */ Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls; return constructFor(enumCls, ai); }
protected EnumKD(EnumResolver<?> er, AnnotatedMethod factory) { super(-1, er.getEnumClass()); _resolver = er; _factory = factory; }
protected CompactStringObjectMap _getToStringLookup(DeserializationContext ctxt) { CompactStringObjectMap lookup = _lookupByToString; // note: exact locking not needed; all we care for here is to try to // reduce contention for the initial resolution if (lookup == null) { synchronized (this) { lookup = EnumResolver.constructUnsafeUsingToString(_enumClass(), ctxt.getAnnotationIntrospector()) .constructLookup(); } _lookupByToString = lookup; } return lookup; } }
private final Enum<?> _deserializeAltString(JsonParser jp, DeserializationContext ctxt, String name) throws IOException { name = name.trim(); if (name.length() == 0) { if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { return null; } } else { // [#149]: Allow use of 'String' indexes as well char c = name.charAt(0); if (c >= '0' && c <= '9') { try { int ix = Integer.parseInt(name); _checkFailOnNumber(ctxt); Enum<?> result = _resolver.getEnum(ix); if (result != null) { return result; } } catch (NumberFormatException e) { // fine, ignore, was not an integer } } } if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdStringException(name, _resolver.getEnumClass(), "value not one of declared Enum instance names: "+_resolver.getEnums()); } return null; }
@Override public Object _parse(String key, DeserializationContext ctxt) throws JsonMappingException { if (_factory != null) { try { return _factory.call1(key); } catch (Exception e) { ClassUtil.unwrapAndThrowAsIAE(e); } } Enum<?> e = _resolver.findEnum(key); if (e == null && !ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdKeyException(_keyClass, key, "not one of values for Enum class"); } return e; } }
/** * @deprecated Since 2.8, use {@link #constructUnsafeUsingMethod(Class, Method, AnnotationIntrospector)} instead. */ @Deprecated public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls, Method accessor) { return constructUnsafeUsingMethod(rawEnumCls, accessor, null); }
/** * @deprecated Since 2.8, use {@link #constructUnsafeUsingToString(Class, AnnotationIntrospector)} instead */ @Deprecated public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls) { return constructUnsafeUsingToString(rawEnumCls, null); }
Enum<?> result = _resolver.findEnum(name); if (result == null && !ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdStringException(_resolver.getEnumClass(), "value not one of declared Enum instance names"); Enum<?> result = _resolver.getEnum(index); if (result == null && !ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdNumberException(_resolver.getEnumClass(), "index value outside legal index range [0.."+_resolver.lastValidIndex()+"]"); throw ctxt.mappingException(_resolver.getEnumClass());
protected EnumResolver<?> constructEnumResolver(Class<?> enumClass, DeserializationConfig config, AnnotatedMethod jsonValueMethod) { if (jsonValueMethod != null) { Method accessor = jsonValueMethod.getAnnotated(); if (config.canOverrideAccessModifiers()) { ClassUtil.checkAndFixAccess(accessor); } return EnumResolver.constructUnsafeUsingMethod(enumClass, accessor); } // [JACKSON-212]: may need to use Enum.toString() if (config.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING)) { return EnumResolver.constructUnsafeUsingToString(enumClass); } return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector()); }