POST MongoDB Расширенный JSON для RepositoryRestController

Я ищу умный или элегантный способ POST MongoDB Extended JSON для REST-контроллера веб-службы, разработанной с помощью Spring Boot (1.5.1).

Мой POJO содержит четко определенные поля (в основном строки), но также Map<String, Object> data with используется для хранения общих данных, что означает, что их специфическая структура неизвестна во время сборки и будет предоставляться клиентами веб-службы. Пожалуйста, не ругайте меня, я знаю, что это плохой выбор дизайна, но меня все равно попросили "сделать это":)

В какой-то момент клиентские данные POST, которые включают ObjectId (в его обычной форме из 24 шестнадцатеричных символов), похожи на это:

{
   ... // other fields that pose no problem
   "data" : {
      "foo" : { "$oid" : "56bb5d05f5dbad5dc6f31af7" }
    }
}

С контроллером, сгенерированным Spring, я получаю "Недопустимое имя поля BSON $oid" java.lang.IllegalArgumentException.

Используя пользовательский RestController, я могу просто привязать тело запроса к String вместо объекта FooBar:

@RestController
@RequestMapping("/foobars")
public class FooBarController {

    // custom repository and resource assembler
    private final FooBarRepository repository;
    private final FooBarResourceAssembler resourceAssembler;

    // autowired constructor
    public ReferenceController(FooBarRepository referenceRepository,
                               FooBarResourceAssembler resourceAssembler) {
        this.repository = referenceRepository;
        this.resourceAssembler = resourceAssembler;
    }

    @PostMapping
    public ResponseEntity<Resource<FooBar>> create(@RequestBody String jsonString) {
        // parse the string using com.mongodb.util.JSON
        DBObject object = (DBObject)JSON.parse(jsonString);

        // convert to a domain object
        FooBar foobar = mongoTemplate.getConverter().read(FooBar.class, object);

        // persist to the database
        foobar = foobar.insert(foobar)

        return ResponseEntity.ok(resourceAssembler.toResource(foobar));
    }
}

Проблема в том, что я теряю преимущество обработки других конечных точек Spring (например, GET /foobar). Поэтому мне нужно использовать RepositoryRestController вместо RestController.

Однако, если я это сделаю, то после размещения упомянутых выше данных у меня появится сообщение "message":"Не удалось прочитать документ: невозможно десериализовать экземпляр java.lang.String из маркера START_OBJECT" org.springframework.http.converter.HttpMessageNotReadableException.

Поэтому мне нужно сделать еще один шаг и напрямую работать с запросом http сервлета:

@RepositoryRestController
@RequestMapping("/foobars")
public class FooBarController {

    ...

    @PostMapping
    public ResponseEntity<Resource<FooBar>> create(HttpServletRequest request) throws IOException {

        // get the raw JSON string from the request
        String jsonString = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

        // parse the string using com.mongodb.util.JSON
        DBObject object = (DBObject)JSON.parse(jsonString);

        // convert to a domain object
        FooBar foobar = mongoTemplate.getConverter().read(FooBar.class, object);

        // persist to the database
        foobar = foobar.insert(foobar)

        return ResponseEntity.ok(resourceAssembler.toResource(foobar));
    }
}

Это работает как чудо, моя пользовательская конечная точка принимает расширенный JSON MongoDB, а Spring обрабатывает другие общие конечные точки. Я просто заинтересован в альтернативных способах достижения того же самого, что может помешать мне добавить этот пользовательский контроллер... некоторую опцию конфигурации для конвертера HTTP-сообщений или для картографа Джексона... или что-нибудь еще, что я мог пропустить.

Заранее спасибо за ваши мысли по этому поводу.

0 ответов

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