Как настроить ObjectMapper на основе атрибута в контексте запроса?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как настроить ObjectMapper на основе атрибута в контексте запроса?

Сообщение Anonymous »

У меня есть приложение с пружинной загрузкой, которое имеет один общий RestController для всех версий и объектов API, т.е.:

Код: Выделить всё

@Controller
@Path("{version: v[1-9][0-9]*|latest}")
@RequiredArgsConstructor
public MyController {
private final LoaderFactory loaderFactory;

@PUT
@Path("/{uri: .+}")
public Response update(String requestBody,
@PathParam("version") String versionParam,
@PathParam("uri") String uri) {
Loader loader = loaderFactory.getLoaderForVersion(versionParam);
Introspector introspector = loader.unmarshal(requestBody, Introspector.class);
return writeToDb(introspector);
}

private String writeToDb(Introspector introspector) {...}
}
и Introspector — это специальные классы, которые используют JAXB и Eclipse Persistence для анализа объектов на основе схемы xsd (одна схема для каждой версии API).
Этот дизайн работает с определением тела запроса и тела ответа как String и выполнением сериализации и десериализации в контроллере.
Я хотел бы изменить его таким образом, чтобы он обрабатывался в фоновом режиме. (от Джексона) и подпись метода изменится на (обратите внимание на requestBody Introspector):

Код: Выделить всё

@PUT
@Path("/{uri: .+}")
public Response update(Introspector requestBody, ...) {...}
Поскольку десериализация Introspector в объект зависит от версии API, стандартная десериализация Jackson не работает. Ему каким-то образом нужно дать указание использовать правильный экземпляр Loader на основе версии API.
Что я пробовал
Пока что , я реализовал собственный IntrospectorDeserializer, реализующий ContextualDeserializer, который корректно работает в тестовом примере:

Код: Выделить всё

  @Test
public void deserialize() throws IOException, AAIUnmarshallingException {
Loader loader = loaderFactory.getLoaderForVersion("v14");
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Introspector.class, new IntrospectorDeserializer()); // IntrospectorDeserializer
// is my custom class
mapper.registerModule(module);

mapper.setConfig(mapper.getDeserializationConfig().withAttribute("loader", loader));

String customer = new String(Files.readAllBytes(Path.of("src/test/resources/customer.json")));
Introspector introspector = mapper.readValue(customer, Introspector.class);
String result = mapper.writeValueAsString(introspector);
JSONAssert.assertEquals(customer, result, false);
}
Здесь экземпляр загрузчика для конкретной версии передается через mapper.setConfig(mapper.getDeserializationConfig().withAttribute("loader", loader)) .
Я не знаю, движусь ли я в правильном направлении, внедряя собственный десериализатор.
Теперь мой вопрос заключается в том, как бы я поручил Джексону каким-то образом использовать мой класс загрузчика и использовать правильный загрузчик на основе версии API, предоставленной через @PathParam?

Подробнее здесь: https://stackoverflow.com/questions/790 ... st-context
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»