我在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");
}
}

08-19 15:54