【问题标题】:Jackson deserialise JsonPatch with object valueJackson 使用对象值反序列化 Json Patch
【发布时间】:2020-07-21 17:48:07
【问题描述】:

我在我的 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 }
]

JsonPatch 实例被 Jackson 正确反序列化

但是对于复杂的值类型(对象):

[
  { "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 正确反序列化

提前感谢您的任何建议或帮助!

【问题讨论】:

  • Class JsonPatch 没有没有参数的构造函数。所以 Spring 不能创建它的实例。考虑使用其他类来复制以下数据。
  • JsonPatch 是接口。我猜你的意思是Apache imp。 JsonPatchImpl。也许其他 JSR-374 实现在反序列化复杂类型方面没有困难?

标签: java json spring json-patch


【解决方案1】:

我通过使用 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");
}
}

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多