Dynamic polymorphic type handling with Jackson

后端 未结 4 1070
暗喜
暗喜 2020-12-31 07:40

I have a class hierarchy similar to this one:

public static class BaseConfiguration {
}

public abstract class Base {
  private BaseConfiguration configurati         


        
4条回答
  •  感情败类
    2020-12-31 08:16

    I had to do something similar, and ended up creating a generic polymorphic list serializer and deserialzer. Here is the deserialize that I think will work for you:

        public class PolymorphicListDeserializer extends JsonDeserializer> implements ContextualDeserializer {
      private HashMap _typeMap = null;
    
      private Class _elementType;
    
      private static  List getNewList(Class clazz) {
        return new ArrayList();
      }
    
      @Override
      public List deserialize(final JsonParser jp, DeserializationContext ctxt) throws IOException {
    
        final List list = getNewList(_elementType);
    
        JsonToken nextToken = jp.getCurrentToken();
    
        if (nextToken == JsonToken.START_OBJECT) {
            if ( _typeMap.containsKey( currentFieldName )) {
              list.add( _elementType.cast( ctxt.readValue( jp, _typeMap.get( currentFieldName ) ) ) );
            }
            nextToken = jp.nextToken();
          } else if (currentFieldName != null && isEndToken(nextToken) && wrapperCount == 0) {
            break;
          } else {
            nextToken = jp.nextToken();
          }
        }
        return list;
      }
    
      public JsonDeserializer> createContextual( DeserializationContext ctxt, BeanProperty property ) throws JsonMappingException {
        //In Jackson 2.6.3, this method is called once per instance and the exception is never thrown
        if ( _typeMap == null )
          _typeMap = new HashMap();
        else
          throw new RuntimeException("Unsupported version of Jackson. Code assumes context is created once and only once.");
    
        _elementType = property.getType().getContentType().getRawClass();
    
        //For now, requiring XmlElements annotation to work.  May add support for JsonElements (if needed) later.
        for (XmlElement e : property.getAnnotation(XmlElements.class).value()) {
          _typeMap.put(e.name(), e.type());
        }
    
        return this;
      }
    
      private static boolean isStartToken(JsonToken t) {
        boolean result = false;
        if (t == JsonToken.START_OBJECT) {
          result = true;
        } else if (t == JsonToken.START_ARRAY) {
          result = true;
        }
        return result;
      }
    

提交回复
热议问题