JSON 由于 ObjectMapper,补丁比较失败?

JSON Patch diffing fails due to ObjectMapper?

我有 2 个对象要比较。为此,我在 spring-boot 版本 2.1.3 中使用 Jackson ObjectMapper 将它们反序列化为字符串,将它们作为树读取(转换为 JsonNode),然后将它们区分为创建一个 JsonPatch 对象。我注意到的是,在现有对象的 JsonNode 中,所有具有 null 值的字段都被跳过,就像只有 null 值字段的对象一样。 ObjectMapper 似乎在消费者(spring-引导版本 2.6.7)和服务提供者(spring-boot-2.1.3)中表现不同。示例,在树中:

"_optionalAttrs":{"styles":{"99_0002_4_24_002":{"hineck":null,"choices":{"99_0002_4_24_002_001":{"color":null}}},"99_0002_4_24_001":{"hineck":null,"choices":null}}.   

"_optionalAttrs":{"styles":{"99_0002_4_24_002":{"choices":{"99_0002_4_24_002_001":{}}},"99_0002_4_24_001":{}}

我猜这就是生成的 JsonPatch 操作不正确的原因:

op: copy; from: "/_optionalAttrs/styles/99_0002_4_24_001/hineck"; path: "/_optionalAttrs/clientAttributes/channel"

我最终收到此错误 - 目标 JSON 文档中没有这样的路径。有没有办法确保两者保持一致?如果您认为还有其他问题,请告诉我。消费者代码是我们可以更改的东西,但服务提供者代码不属于我们所有。我正在使用 json-patch-1.12jdk 11.

我没有很好的解决方案,但总比没有好 您可以使用 fieldAndValueMap 方法将对象映射到 Map 并比较它们

    public Map<String, String> fieldAndValueMap(Class<?> type, Object obj) throws ReflectiveOperationException {
        Map<String, String> result = new HashMap<>();
        for (Field field : type.getDeclaredFields()) {
            field.setAccessible(true);
            if (isWrapperType(field.getType())) {
                String value = nonNull(field.get(obj)) ? field.get(obj).toString() : "null";
                result.put(type.getSimpleName() + "." + field.getName(), value);
            } else {
                String getMethod = "get" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
                Method method = type.getMethod(getMethod);
                Object subObj = method.invoke(obj);
                if (nonNull(subObj)) {
                    result.putAll(fieldAndValueMap(field.getType(), subObj));
                }
            }
        }
        return result;
    }

    public boolean isWrapperType(Class<?> type) {
        return getWrapperTypes().contains(type);
    }

    private Set<Class<?>> getWrapperTypes() {
        Set<Class<?>> ret = new HashSet<>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(String.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        ret.add(BigDecimal.class);
        ret.add(LocalDate.class);
        ret.add(LocalDateTime.class);
        ret.add(LocalTime.class);
        ret.add(Date.class);
        return ret;
    }
获取对象作为字段和值的映射:fieldAndValueMap(firstObject.getClass(), firstObject)

默认情况下,ObjectMapper 将保留 null 个值,但您可以使用以下设置跳过它们:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)