如何用Jackson将JSON数组反序列化为非集合类Java对象
问题描述
此前因实际需求从Gson切换至Jackson,原Gson代码可将如下结构的JSON数组反序列化为自定义PermissionOverwrites对象:
[ { "id": "111111111111111111", "type": "0", "allow": "01010", "deny": "10101" } ]
原Gson实现逻辑:
JsonArray array = json.getAsJsonArray(); Map<Permissionable, Permissions> map = new HashMap<>(); for (JsonElement element : array) { JsonObject object = element.getAsJsonObject(); Permissionable p = switch (object.get("type").getAsInt()) { case 0 -> new Permissionable.MockPermissionable(object.get("id").getAsLong()); case 1 -> new Permissionable.MockPermissionable(object.get("id").getAsLong()); default -> throw new JsonParseException("Unknown permissionable type"); }; Permissions perms = new Permissions(object.get("allow").getAsLong(), object.get("deny").getAsLong()); map.put(p, perms); } return new PermissionOverwrites(map);
现使用Jackson时,仅持有JsonParser和DeserializationContext,不知如何解析数组完成相同功能,求实现方案。
补充PermissionOverwrites类代码:
@ToString @EqualsAndHashCode public class PermissionOverwrites { private Map<Permissionable, Permissions> overwrites; public PermissionOverwrites(Map<Permissionable, Permissions> overwrites) { this.overwrites = overwrites; } public PermissionOverwrites() { this.overwrites = new HashMap<>(); } public Map<Permissionable, Permissions> getOverwrites() { return Collections.unmodifiableMap(overwrites); } }
解决方案
在Jackson中,可通过自定义JsonDeserializer实现相同解析逻辑,核心是利用JsonParser遍历JSON数组元素,逐个解析构建目标对象:
1. 自定义PermissionOverwrites反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class PermissionOverwritesDeserializer extends JsonDeserializer<PermissionOverwrites> { @Override public PermissionOverwrites deserialize(JsonParser parser, DeserializationContext context) throws IOException { // 将JsonParser转换为JsonNode数组 JsonNode arrayNode = parser.getCodec().readTree(parser); if (!arrayNode.isArray()) { throw new IOException("Expected JSON array for PermissionOverwrites"); } Map<Permissionable, Permissions> overwritesMap = new HashMap<>(); for (JsonNode elementNode : arrayNode) { ObjectNode objectNode = (ObjectNode) elementNode; // 解析字段:JSON中为字符串类型,自动转为对应数值 int type = objectNode.get("type").asInt(); long id = objectNode.get("id").asLong(); long allow = objectNode.get("allow").asLong(); long deny = objectNode.get("deny").asLong(); // 根据type创建Permissionable实例 Permissionable permissionable = switch (type) { case 0, 1 -> new Permissionable.MockPermissionable(id); default -> throw new IOException("Unknown permissionable type: " + type); }; // 构建Permissions并存入Map Permissions permissions = new Permissions(allow, deny); overwritesMap.put(permissionable, permissions); } return new PermissionOverwrites(overwritesMap); } }
2. 注册反序列化器
有两种注册方式可选:
- 方式一:类上注解标注
直接在PermissionOverwrites类添加注解绑定反序列化器:
@ToString @EqualsAndHashCode @JsonDeserialize(using = PermissionOverwritesDeserializer.class) public class PermissionOverwrites { // 原类代码保持不变 }
- 方式二:ObjectMapper手动注册
若无法修改目标类,可在初始化ObjectMapper时注册:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; SimpleModule module = new SimpleModule(); module.addDeserializer(PermissionOverwrites.class, new PermissionOverwritesDeserializer()); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(module); // 后续使用该objectMapper完成反序列化 PermissionOverwrites overwrites = objectMapper.readValue(jsonString, PermissionOverwrites.class);
关键说明
- 通过
parser.getCodec().readTree(parser)将JsonParser转换为JsonNode,方便遍历数组元素 - Jackson的
asInt()/asLong()方法支持自动将字符串类型的数值转为对应基本类型 - 异常处理逻辑与原Gson实现保持一致,遇到未知type直接抛出异常
内容的提问来源于stack exchange,提问作者RedDev
相关产品推荐
相关产品推荐

