You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免在PostgreSQL JSONB中存储Null字段并改造转换器代码

解决PostgreSQL JSONB存储时移除Null字段的可扩展方案

需求说明

向PostgreSQL的JSONB类型存储数据时,需要避免存储值为Null的字段,同时要保留原有代码结构并具备可扩展性。现有转换代码及当前存储的含大量Null字段的JSON示例如下:

现有转换代码

public class JsonbConverter implements AttributeConverter<Map<String, Object>, String> {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(Map<String, Object> details) {
        String value = null;

        try {
            if (details == null || details.isEmpty()) {
                return value;
            }

            value = objectMapper.writeValueAsString(details);
        }
        catch (JsonProcessingException jpe) {
            log.error("unable to convert details to db {}", details, jpe);
        }

        return value;
    }

    @Override
    public Map<String, Object> convertToEntityAttribute(String dbData) {
        Map<String, Object> value = null;

        try {
            if (dbData == null) {
                return value;
            }

            value = objectMapper.readValue(dbData, new TypeReference<Map<String, Object>>() {
            });
        }
        catch (IOException ioe) {
            log.error("unable to convert details to entity {}", dbData, ioe);
        }

        return value;
    }

}

当前存储的JSON示例

{"categories": [{"name": "News", "label": null, "taxonomyUri": null}, {"name": "UK News", "label": null, "taxonomyUri": null}, {"name": "Crime", "label": null, "taxonomyUri": null}, {"name": "Dogs", "label": null, "taxonomyUri": null}, {"name": "Parenting advice", "label": null, "taxonomyUri": null}, {"name": "Pets", "label": null, "taxonomyUri": null}, {"name": "Police", "label": null, "taxonomyUri": null}]}

解决方案

1. 基础方案:配置ObjectMapper全局忽略Null字段

这是最简洁的实现方式,无需额外遍历处理,直接通过Jackson的配置实现Null字段过滤:

private final ObjectMapper objectMapper = new ObjectMapper()
        .setSerializationInclusion(JsonInclude.Include.NON_NULL);

修改后,序列化Map为JSON字符串时,所有值为Null的字段会自动被忽略,完全保留原有转换器结构。

2. 可扩展方案:自定义过滤工具类(适配复杂场景)

如果需要更灵活的过滤规则(比如指定某些字段即使为Null也要保留、过滤空字符串等),可以封装工具类处理数据,保持转换器的简洁性:

步骤1:创建Null字段过滤工具类

public class JsonNullFilter {
    public static Map<String, Object> removeNullFields(Map<String, Object> data) {
        if (data == null) return null;
        Map<String, Object> filtered = new HashMap<>();
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            Object value = entry.getValue();
            if (value != null) {
                // 递归处理嵌套的Map或集合
                if (value instanceof Map) {
                    filtered.put(entry.getKey(), removeNullFields((Map<String, Object>) value));
                } else if (value instanceof Collection) {
                    filtered.put(entry.getKey(), processCollection((Collection<?>) value));
                } else {
                    filtered.put(entry.getKey(), value);
                }
            }
        }
        return filtered;
    }

    private static Collection<?> processCollection(Collection<?> collection) {
        List<Object> processed = new ArrayList<>();
        for (Object item : collection) {
            if (item instanceof Map) {
                processed.add(removeNullFields((Map<String, Object>) item));
            } else {
                processed.add(item);
            }
        }
        return processed;
    }
}

步骤2:修改转换器集成工具类

@Override
public String convertToDatabaseColumn(Map<String, Object> details) {
    String value = null;
    try {
        if (details == null || details.isEmpty()) {
            return value;
        }
        // 先过滤Null字段,再执行序列化
        Map<String, Object> filteredDetails = JsonNullFilter.removeNullFields(details);
        value = objectMapper.writeValueAsString(filteredDetails);
    } catch (JsonProcessingException jpe) {
        log.error("unable to convert details to db {}", details, jpe);
    }
    return value;
}

这种方式可以轻松扩展过滤逻辑,比如在工具类中添加参数控制特定字段的保留规则,或是处理空字符串等其他空值场景。

3. 效果验证

修改后,存储的JSON会自动移除所有Null值字段,最终结果如下:

{"categories": [{"name": "News"}, {"name": "UK News"}, {"name": "Crime"}, {"name": "Dogs"}, {"name": "Parenting advice"}, {"name": "Pets"}, {"name": "Police"}]}

内容的提问来源于stack exchange,提问作者user352290

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:03:22