Принять произвольный JSON как RequestBody весной

Как следует из названия, я бы хотел, чтобы мой класс контроллера принимал (в основном) произвольный JSON в RequestBody как часть POST. Прежде чем вы спросите, почему мне нужен неработающий JSON, это потому, что JSON просто проходит через серверную часть хранилища с минимальной обработкой (извлекается только одно поле).

В этом JSON есть три обязательных поля: data, schema и resourceID. Вот как выглядит мой класс запроса:

public class MyRequestBody implements Serializable {

    private JsonObject data;
    private JsonObject schema;
    private String resourceID;
    ...

Я уже понимаю проблемы сериализации, из-за которых это не работает. Причина, по которой я не хочу расширять эту модель данных для определения полей для data и schema, заключается в том, что я просто не знаю, насколько они будут вложенными. Вот почему я просто не использую Map<String, String>.

Есть ли простое решение для получения произвольных вложенных данных JSON как части RequestBody, или я вынужден либо написать большую строго типизированную модель данных, либо принять ее как Object, преобразовать в JSON и где-нибудь выполнить проверку всех моих полей еще?

Подпись контроллера для справки:

@RequestMapping(value = "test/data", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public ResponseEntity<StorageData> publishData(@RequestBody MyRequest requestBody) {

Вот пример JSON. Там, где все становится рискованно, находятся в разделе data и schema, где они могут содержать несколько уровней вложенности, о которых я бы не знал:

{
    "data": {
        "display": "bilbo_baggins"
    },
    "resourceID": "0123456789",
    "schema": {
        "type": "record",
        "namespace": "com.org.test",
        "name": "mySchema",
        "fields": [{
            "name": "display",
            "type": "string"
        }]
    }
}

Я не думаю, что слежу за тем, как именно вы собираетесь извлекать эти поля из произвольного JSON, если вы не знаете точно, насколько они будут вложенными. Хотите показать пример?

kumesana 16.07.2018 19:59

Я добавил пример. Единственное поле, которое мне нужно извлечь, - это resourceID, которое всегда будет верхнего уровня. Поля data и schema вызывают у меня проблемы, потому что я не знаю, как и могу ли я их принять, не определив четко, как они выглядят. Это приложение просто сохраняет все данные с использованием идентификатора ресурса, но остальной контент не имеет отношения к моему приложению.

J_Stan 16.07.2018 20:02

Вы можете просто использовать Map <String, Object> и получить свой идентификатор ресурса из этой карты.

JB Nizet 16.07.2018 20:10

Обратите внимание, что использование Map<String, Object> вызовет у вас многочисленные головные боли при проверке и в значительной степени сведет на нет любые преимущества, которые вы пытались бы получить от Spring Controller. Почему одна конечная точка используется для стольких разных типов данных? Вы собираетесь «переписать» эту устаревшую систему? Если да, то почему бы не сделать это правильно и не создать конечную точку для каждого типа запроса (который, вероятно, в любом случае описывает различные объекты и действия домена)?

user991710 16.07.2018 20:15

Он действительно не используется для нескольких типов данных, я не уверен, почему вы так думаете. Поскольку вам нужен контекст, поле schema представляет собой схему Avro, связанную с полем data. Эта конечная точка находится перед системой Kafka, поэтому их нужно связать вместе. Я пытаюсь написать это таким образом, чтобы у меня не было большой строго типизированной модели данных, а также чтобы я мог повторно использовать эту конечную точку для любой темы Kafka, которую я хочу.

J_Stan 16.07.2018 20:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
6
5
6 658
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вы можете получить объект JsonNode для произвольного JSON

Как это:

@RequestMapping(value = "test/data", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public ResponseEntity<StorageData> publishData(@RequestBody JsonNode requestBody) {.. }
  1. Измените класс MyRequestBody, чтобы использовать JsonNode вместо JsonObject для данные и схема. Вам не нужно реализовывать Serializable, если он вам не нужен для чего-то еще в вашем коде, но он не нужен для получения объектов Json в запросе.

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