jackson JSON修补程序差异化是否因ObjectMapper而失败?

pu3pd22g  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(148)

我有两个对象要进行diff运算,为此我在spring-boot 2.1.3版中使用Jackson ObjectMapper将它们反序列化为String,把它们当作一棵树来读(转换为JsonNode),然后对它们进行diff运算以创建一个JsonPatch对象。我注意到的是,在现有对象中's JsonNode跳过所有具有null值的字段,因为对象只具有null值字段。(spring-boot版本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

x8diyxa7

x8diyxa71#

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

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
zbdgwd5y

zbdgwd5y2#

我没有很好的解决方案,但总比什么都没有好。您可以使用 fieldAndValueMap 方法将对象Map到Map〈String,String〉,然后比较它们

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;
    }
  • 以字段和值Map形式获取对象 *:如果您有一个对象,请使用

相关问题