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-сообщений или для картографа Джексона... или что-нибудь еще, что я мог пропустить.
Заранее спасибо за ваши мысли по этому поводу.