2015-04-08 4 views
3

Поставщики контента Jackson jax-rs используются в нашем проекте REST API, основанном на jax-rs, для обработки типа содержимого json и xml. В ответ POJO у нас есть структура карты, и наше требование состоит в том, чтобы сериализовать эту структуру карты как Список в XML и как карту в формате JSON. (Ключи карты содержат пробелы и, следовательно, невозможно преобразовать эти ключи в имена XML-элементов). Для достижения этой цели мы внедрили пользовательский сериализатор для XML ...Jackson: Регистрация пользовательского XML-сериализатора для структуры данных карты

JSON:

"properties":{ 
    "a b c":{ 
      "name": "a b c", 
      "value": "xyz" 
      } 
} 

XML:

<property name="a b c" value="xyz"/> 

PropertyMapSerializer:

public class PropertyMapSerializer extends 
     JsonSerializer<Map<String, Property>> { 

    @Override 
    public void serialize(Map<String, Property> value, JsonGenerator jgen, 
      SerializerProvider provider) throws IOException, 
      JsonProcessingException { 

     provider.defaultSerializeValue(value.values(), jgen); 
    } 
} 

JAX-RS context resolver настроен для разрешения экземпляра XMLMapper, настроенного для использования этого сериализатора.

@Provider 
@Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML }) 
public class XmlMapperContextResolver implements ContextResolver<XmlMapper> { 
    private final XmlMapper xmlMapper = new XmlMapper(); 

    @Override 
    public XmlMapper getContext(Class<?> type) { 
     return xmlMapper; 
    } 

    public XmlMapperContextResolver() { 
     JacksonXmlModule module = new JacksonXmlModule(); 
     module.setDefaultUseWrapper(false); 

     //Compilation error while adding Serializer for Map and HashMap class. 
     //Error: The method addSerializer(Class<? extends T>, JsonSerializer<T>) in the type SimpleModule is not applicable for the arguments (Class<Map>, PropertyMapSerializer) 
     //module.addSerializer(HashMap.class, new PropertyMapSerializer()); 
     //module.addSerializer(Map.class, new PropertyMapSerializer()); 

     //This works 
     module.addSerializer(PropertyMap.class, new PropertyMapSerializer()); 

     xmlMapper.configure(SerializationFeature.INDENT_OUTPUT, true); 
     xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); 
     xmlMapper.registerModule(module); 
    } 
} 

Где PropertyMap подкласс HashMap: POJO

public class PropertyMap extends HashMap<String, Property> { 
} 

Ответа:

public class ResponsePOJO { 
    //Commenting out as serializer couldn't be added for HashMap 
    //private Map<String, Property> properties = new HashMap<String, Property>(); 
    private Map<String, Property> properties = new PropertyMap(); 
} 

Не мог бы вы, пожалуйста, дайте мне знать, почему я не может добавить сериализатора для HashMap при добавлении Сериализатор для поддержки нашего подкласса? Из-за этого я вынужден создавать подклассы стандартных структур данных для добавления пользовательских сериализаторов.

Но в то же время добавления пользовательского сериализатора с помощью аннотаций к карте поддерживается и она работает:

@JsonSerialize(using=PropertyMapSerializer.class) 
private Map<String, Property> properties = new HashMap<String, Property>(); 

Добавление сериалайзера таким образом сделает сериализатор применим как для JSON и XML-формата. К сожалению, я не могу этого сделать, поскольку этот сериализатор применим только для формата XML. Пожалуйста, поделитесь своими мыслями.

ответ

0

Я не знаю, поможет ли это, но я нашел, что это работает для меня. Внутри мой сериализатор я переопределить метод HandleType() как так:

public class MapToTuple extends JsonSerializer<Map<String, Property>> { 

    @Override 
    public void serialize(final Map<String, Property> map, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { 
      /*Serializing code here*/ 
    } 

    @Override 
    public Class<Map<String, Property>> handledType() { 
     Class<Map<String, Property>> typeClass = (Class<Map<String, Property>>)(Class<?>)Map.class; 
     return typeClass; 
    } 
} 

И тогда я зарегистрировать сериалайзер так:

SimpleModule mapSerializerModule = new SimpleModule("MapSerializerModule", new Version(1, 0, 0, "beta")); 
    mapSerializerModule.addSerializer(new MapToTuple()); 

    mapper.registerModule(mapSerializerModule); 

Надеется, что это помогает.

Смежные вопросы