我在Spring项目PATCH端点中将JsonPatch(JSR-374)与Apache org.apache.johnzon:johnzon-core:1.2.4的实现一起使用:
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.registerModule(new Jdk8Module());
objectMapper.registerModule(new JSR353Module());
return objectMapper;
}
控制者
@PatchMapping("/settings")
public ResponseEntity<SettingsResponse> patchSettings(@RequestBody JsonPatch patchDocument, Locale locale) {...}
用json请求的简单原子值
[
{ "op": "replace", "path": "/currency", "value": "EUR" },
{ "op": "test", "path": "/version", "value": 10 }
]
Jackson正确反序列化了JsonPatch实例
但是具有复杂的值类型(对象):
[
{ "op": "replace", "path": "/currency", "value": {"code": "USD", "label": "US Dollar"} },
{ "op": "test", "path": "/version", "value": 10 }
]
抛出异常
引起原因:com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造
javax.json.JsonPatch
的实例(不存在创建者,如默认构造一样):抽象类型要么需要映射到具体类型,要么具有自定义反序列化器,要么包含附加类型信息在[来源:(PushbackInputStream);行:1,列:1]
我侦察JsonPatch(及其Apache JsonPatchImpl)能够处理复杂类型,因为JsonValue提到了JsonObject和ValueType.OBJECT,但是我不知道如何指示Jackson正确地反序列化
在此先感谢您的任何建议或帮助!
最佳答案
我通过使用JSR-364实现Json.createPatch进行了此操作:
@PatchMapping("/settings")
public ResponseEntity<SettingsResponse> patchDefaultSettingsJsonP3(@RequestBody String patchString, Locale locale) {
try (JsonReader jsonReader = Json.createReader(new StringReader(patchString))) {
JsonPatch patch = Json.createPatch(jsonReader.readArray());
...
}
}
编辑:
通过将转换器注册为Bean,我找到了更明智的解决方案。然后,Spring在内部负责反序列化
@Component
public class JsonPatchHttpMessageConverter extends AbstractHttpMessageConverter<JsonPatch> {
public JsonPatchHttpMessageConverter() {
super(MediaType.valueOf("application/json-patch+json"), MediaType.APPLICATION_JSON);
}
@Override
protected boolean supports(Class<?> clazz) {
return JsonPatch.class.isAssignableFrom(clazz);
}
@Override
protected JsonPatch readInternal(Class<? extends JsonPatch> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
try (JsonReader reader = Json.createReader(inputMessage.getBody())) {
return Json.createPatch(reader.readArray());
} catch (Exception e) {
throw new HttpMessageNotReadableException(e.getMessage(), inputMessage);
}
}
@Override
protected void writeInternal(JsonPatch jsonPatch, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
throw new NotImplementedException("The write Json patch is not implemented");
}
}