Restlet Complex Object to XML serializaton

前端 未结 1 951
我寻月下人不归
我寻月下人不归 2020-12-18 16:36

I have restlet web service which returns response as xml. I\'m using Jackson as binder. below is class I\'m returning.

 import java.io.Serializable;
    impo         


        
相关标签:
1条回答
  • 2020-12-18 17:33

    This is the default serialization with Jackson. However you can leverage custom serializer to improve this. This feature allows you to have the hand on the generated content within Jackson for a specific class. You can override the default strategy with your own and configure in a very fine manner what will be created.

    Below a sample of such entity that generates content for the class SomeBean:

    public class SomeBeanSerializer extends JsonSerializer<SomeBean> {
        @Override
        public void serialize(SomeBean bean, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                      JsonProcessingException {
            jgen.writeStartObject();
    
            // Fields
            jgen.writeNumberField("id", bean.getId());
            (...)
    
            // Link
            String href = (...)
            HypermediaLink linkToSelf = new HypermediaLink();
            linkToSelf.setHref(href + bean.getId());
            linkToSelf.setRel("self");
            jgen.writeObjectField("hypermediaLink", linkToSelf);
    
            jgen.writeEndObject();
        }
    }
    

    Here is the way to configure this within Restlet:

    JacksonConverter jacksonConverter = getRegisteredJacksonConverter();
    
    if (jacksonConverter != null) {
        ObjectMapper objectMapper = jacksonConverter.getObjectMapper();
        SimpleModule module = new SimpleModule("MyModule", new Version(1, 0, 0, null));
        module.addSerializer(SomeBean.class, new SomeBeanSerializer());
        objectMapper.registerModule(module);
    }
    

    This link could help you to see how to configure the Jackson converter of Restlet: https://templth.wordpress.com/2015/02/23/optimizing-restlet-server-applications/. It provides the content of the method getRegisteredJacksonConverter.

    Edited: with version 2.3 of Restlet, something changes at this level. The object mapper is now brought by the JacksonRepresentation instead of the JacksonConverter itself. The object mapper is now instantiated for each representation of this kind. This means that you need to sub class these two elements to configure the custom serializer.

    Here is the code of the class CustomJacksonRepresentation:

    public class CustomJacksonRepresentation<T>
                    extends JacksonRepresentation<T> {
        @Override
        public ObjectMapper getObjectMapper() {
            if (this.objectMapper == null) {
                this.objectMapper = createObjectMapper();
                SimpleModule module = new SimpleModule("MyModule",
                                        new Version(1, 0, 0, null));
                module.addSerializer(SomeBean.class,
                                   new SomeBeanSerializer());
                objectMapper.registerModule(module);
            }
            return this.objectMapper;
        }
    }
    

    Here is the code of the class CustomJacksonConverter:

    public class CustomJacksonConverter
                    extends JacksonConverter {
        protected <T> JacksonRepresentation<T> create(
                            MediaType mediaType, T source) {
            return new CustomJacksonRepresentation<T>(
                                     mediaType, source);
        }
    
        protected <T> JacksonRepresentation<T> create(
                  Representation source, Class<T> objectClass) {
            return new CustomJacksonRepresentation<T>(
                                     source, objectClass);
        }
    }
    

    This implemented, you need to replace the existing jackson converter that is automatically registered by Restlet. Here is the code to do that:

    // Looking for the registered jackson converter
    JacksonConverter jacksonConverter = null;
    List<ConverterHelper> converters
             = Engine.getInstance().getRegisteredConverters();
    for (ConverterHelper converterHelper : converters) {
        if (converterHelper instanceof JacksonConverter) {
            jacksonConverter = (JacksonConverter) converterHelper;
            break;
        }
    }
    
    // converters
    Engine.getInstance().getRegisteredConverters().remove(
                                           jacksonConverter);
    CustomJacksonConverter customJacksonConverter
                              = new CustomJacksonConverter();
    Engine.getInstance().getRegisteredConverters().add(
                                     customJacksonConverter);
    

    You can notice that the way to manage converters will be refactored in the version 3 of Restlet to make things more convenient to configure! ;-)

    Hope it helps you, Thierry

    0 讨论(0)
提交回复
热议问题