【问题标题】:Restlet Complex Object to XML serializatonRestlet 复杂对象到 XML 序列化
【发布时间】:2015-05-01 03:34:27
【问题描述】:

我有以 xml 形式返回响应的 restlet 网络服务。我正在使用杰克逊作为粘合剂。 下面是我要返回的课程。

 import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;

    public class ApiResponse<T> implements Serializable {

        /**
         * 
         */
        private static final long serialVersionUID = -2736991050157565598L;

        private int responseCode;
        private String reponseMessage;
        private List<T> body = new ArrayList<T>();

        public int getResponseCode() {
            return responseCode;
        }

        public void setResponseCode(int responseCode) {
            this.responseCode = responseCode;
        }

        public String getReponseMessage() {
            return reponseMessage;
        }

        public void setReponseMessage(String reponseMessage) {
            this.reponseMessage = reponseMessage;
        }

        public List<T> getBody() {
            return body;
        }

        public void setBody(List<T> body) {
            this.body = body;
        }

    }

以下是服务的响应。除了将嵌套对象的属性名称与父对象相同之外,一切几乎都很好。它显示嵌套标签名称的主体,但我希望它是 T 模板。有什么想法吗?

<ApiResponse>
    <responseCode>1</responseCode>
    <reponseMessage />
     <body>
        <body>
          <reportId>1</reportId>
          <reportName>name1</reportName>
        </body>
        <body>
          <reportId>2</reportId>
          <reportName>name2</reportName>
        </body>
     </body>
</ApiResponse>

【问题讨论】:

    标签: java xml serialization deserialization restlet-2.0


    【解决方案1】:

    这是 Jackson 的默认序列化。但是,您可以利用自定义序列化程序来改进这一点。此功能允许您在 Jackson 中为特定课程生成内容。您可以用自己的策略覆盖默认策略,并以非常精细的方式配置将要创建的策略。

    下面是为类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();
        }
    }
    

    这是在 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);
    }
    

    此链接可以帮助您了解如何配置 Restlet 的 Jackson 转换器:https://templth.wordpress.com/2015/02/23/optimizing-restlet-server-applications/。它提供了方法getRegisteredJacksonConverter的内容。

    已编辑:使用 2.3 版的 Restlet,此级别发生了一些变化。对象映射器现在由JacksonRepresentation 而不是JacksonConverter 本身带来。现在为这种类型的每个表示实例化对象映射器。这意味着您需要对这两个元素进行子类化以配置自定义序列化程序。

    这是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;
        }
    }
    

    这是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);
        }
    }
    

    这个实现了,需要替换现有的由Restlet自动注册的jackson转换器。这是执行此操作的代码:

    // 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);
    

    您可以注意到管理转换器的方式将在 Restlet 版本 3 中进行重构,以使配置更方便! ;-)

    希望对你有帮助 蒂埃里

    【讨论】:

    • 似乎新版本的 JacksonConverter 没有提供对象映射器实例。有什么更好的方法来获得它?
    • 是的,你是对的! Restlet 2.3 版本发生了变化。我为此版本添加了新方法。希望它可以帮助你;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多