Рестлет сложного объекта в XML-сериализацию

У меня есть веб-сервис рестлет, который возвращает ответ в виде XML. Я использую Джексона в качестве связующего. ниже класс, который я возвращаю.

 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>

1 ответ

Это сериализация по умолчанию с Джексоном. Однако вы можете использовать собственный сериализатор, чтобы улучшить это. Эта функция позволяет вам иметь дело с сгенерированным контентом в Джексоне для определенного класса. Вы можете переопределить стратегию по умолчанию своей собственной и очень точно настроить, что будет создано.

Ниже приведен пример такого объекта, который генерирует контент для класса. 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: 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. Вот код для этого:

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

Вы можете заметить, что способ управления конвертерами будет изменен в версии 3 Restlet, чтобы сделать его более удобным в настройке!;-)

Надеюсь, это поможет тебе, Тьерри

Другие вопросы по тегам