Jackson:為Map數據結構注冊自定義XML序列化程序

[英]Jackson: Registering a custom XML serializer for Map data structure


Jackson jax-rs content providers are used in our jax-rs based REST API project, to handle json and xml content type. In response POJO, we have map structure and our requirement is to serialize this map structure as a List in XML and as a Map in JSON format. (The map keys contain whitespaces and hence its not possible to convert these keys as XML element names). In order to achieve this we have implemented a custom serializer for XML...

Jackson jax-rs內容提供程序用於我們基於jax-rs的REST API項目,用於處理json和xml內容類型。作為回應POJO,我們有地圖結構,我們的要求是將此地圖結構序列化為XML格式的List和JSON格式的Map。 (映射鍵包含空格,因此無法將這些鍵轉換為XML元素名稱)。為了實現這一目標,我們為XML實現了一個自定義序列化程序...

JSON:

JSON:

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

XML:

XML:

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

PropertyMapSerializer:

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 is configured to resolve the XMLMapper instance configured to use this serializer.

JAX-RS上下文解析器配置為解析配置為使用此序列化程序的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);
    }
}

Where PropertyMap is a subclass of HashMap:

其中PropertyMap是HashMap的子類:

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

Response POJO:

回復POJO:

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();
}

Could you please let me know, why I am not able add serializer for HashMap while adding serializer for its subclass us supported? Because of this I am forced to create subclasses of standard data structures to add custom serializers.

能不能讓我知道,為什么我不能為HashMap添加序列化器,同時為我們支持的子類添加序列化器?因此我不得不創建標准數據結構的子類來添加自定義序列化程序。

But at the same time adding custom serializer using annotations for Map is supported and it works:

但同時支持使用Map的注釋添加自定義序列化程序,它可以工作:

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

Adding serializer in this manner would make the serializer applicable for both json and xml format. Unfortunately, I can't do this as this serializer is only applicable for XML format. Please share your thoughts.

以這種方式添加序列化程序將使序列化程序適用於json和xml格式。不幸的是,我不能這樣做,因為這個序列化器只適用於XML格式。請分享你的想法。

1 个解决方案

#1


0  

I don't know if this is going to help, but I found this works for me. Inside my serializer I override the handleType() method like so:

我不知道這是否會有所幫助,但我發現這對我有用。在我的序列化程序中,我重寫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;
     }
}

And then I register the serializer like this:

然后我注冊這樣的序列化器:

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

    mapper.registerModule(mapSerializerModule);

Hope this helps.

希望這可以幫助。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/04/08/7206a41523f0321f9733ca5ec4cddcb9.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com