#java #json #jackson #json-api #spring-webclient
#java #json #джексон #json-api #spring-webclient
Вопрос:
Я создаю клиент SpringBoot (используя WebClient для фактического вызова), который будет извлекать данные из REST API поставщика (поэтому у нас нет контроля над структурой ответа). Независимо от вызываемой конечной точки все ответы завернуты в либо
{
"data": {
"attributes": {
// DESIRED FIELDS
}
}
}
или
{
"data": [
{
"attributes": {
// DESIRED FIELDS
}
},
{
"attributes": {
// SAME DESIRED FIELDS WITH DIFFERENT VALUES
}
},
...
]
}
Единственный способ, которым когда-либо будут использоваться данные атрибуты, — это получить доступ к данным, заключенным в них, поэтому я ищу «невидимую руку», которую я мог бы настроить для автоматического извлечения и возврата только внутренних POJO (ов), предпочтительно во время процесса десериализации.
Существует ~ 30 POJO (которые могут быть объединены в любую иерархическую / структуру отношений по мере необходимости), которые были созданы для представления различных ответов, которые мы можем получить от поставщика (упакованных во внутренний jar для повторного использования), поэтому для каждого из них необходимо написать пользовательский десериализатор / конструктор / распаковщик / etcна самом деле это не вариант, и я упираюсь в стену, пытаясь создать универсальный десериализатор или декодер.
Поскольку у нас нет контроля / влияния на то, как поставщик возвращает данные, использование полиморфной десериализации Джексона здесь не вариант AFAIK, поскольку нет способа встроить идентификационные поля в сериализованные данные, и при этом не существует каких-либо уникальных собственных полей, которые могли бы надежно идентифицировать любой данный корень /родительский объект в их JSON (поставщик любит повторно использовать общие поля, такие как id и name).
Учитывая это, существует ли подход, который мог бы обеспечить извлечение за кулисами? Сработало бы даже что-то вроде перехвата любой попытки десериализации JSON, поиска данных (оба массива перестановки объектов) поля атрибутов, а затем ручного преобразования JSON в желаемую структуру, но я не могу найти никакой документации WebClient или Jackson, которая предполагает существование, я думаю, «обхода», десериализатор / декодер, который позволил бы цепочке продолжаться в обычном режиме после реструктуризации.
В худшем случае, я могу создать универсальный класс-оболочку с вспомогательными методами для извлечения базового POJOs после десериализации, и его можно использовать в сочетании с цепными вызовами WebClient, но это не сильно уменьшает раздувание / шаблонность.
Комментарии:
1. Мне интересно услышать, как вы в конечном итоге работаете с этим. Это похоже на JSON: API (и я пометил это), и я написал некоторый код поддержки, не готовый к совместному использованию, для написания всего этого, но не для его чтения (что намного сложнее, потому что JavaScript-ковбои с удовольствием позволяют
data
быть объектом или массивом, объекты ссылок могут бытьстрока или объект и т.д.). Я рассматривал возможность создания библиотеки общего назначения, но еще не начал.2. Я не слышал о JSON: API; спасибо за информацию об этом! К сожалению, из того, что я вижу, это в основном просто стандартизированный подход к полиморфной десериализации, и поскольку наш поставщик не использует поля типа, я действительно изо всех сил пытаюсь найти путь к общему решению по этому вопросу. В настоящее время я обдумываю идею двухэтапного процесса, который десериализует данные атрибуты, но сохраняет необработанный json во вложенном поле, а затем возвращает необработанный json после передачи его через десериализатор типа, который пользователь передает? Хотя, похоже, не отличается от класса-оболочки
3. А, понятно. Если поставщик не может включить поля типа (на том же уровне
attributes
, а не внутри него!), Тогда жизнь будет неприятной. Возможно, свяжитесь с ними и отметьте это, попросив исправить? Это нарушение спецификации JSON: API. (Обратите внимание, конечно, что даже в лучшем случае JSON: API определяет структуру оболочки, и поэтому я заканчиваюJsonApiDataResponse<JsonApiResource<E>>
.)4. К сожалению, они не были особенно восприимчивы, но попробовать стоит. И да, но если бы было поле type, теоретически было бы возможно написать десериализатор, который мог бы пропускать поля data attributes, чтобы только десериализовать внутренний POJO, и позволить людям регистрировать это, когда они делают звонки поставщику, верно? Вероятно, это слишком близко к чрезмерной разработке, но поскольку мы знаем, какой POJO нам понадобится, когда мы обращаемся к поставщику, можно ли манипулировать JSON до того, как он будет десериализован, чтобы вручную ввести поле типа?
5. На самом деле, нам даже не пришлось бы использовать пользовательский десериализатор. Похоже, мы могли бы встроить github.com/jasminb/jsonapi-converter в банку POJO, и это позаботилось бы об этом за нас, пока у нас было поле типа …. так близко, но так далеко