Jackson反序列化:处理JSON数组到嵌套List的Java对象映射

Jackson反序列化:处理JSON数组到嵌套List的Java对象映射

本文深入探讨了在使用jackson库将json数组反序列化为包含嵌套列表的java对象时常见的`mismatchedinputexception`问题。文章详细分析了json结构与pojo定义不匹配的原因,并提供了三种解决方案:直接解析为列表、调整json结构,以及通过自定义反序列化器实现灵活映射,旨在帮助开发者高效解决此类序列化挑战。

在Java开发中,我们经常需要将JSON字符串转换为Java对象(POJO)。Jackson是一个流行的JSON处理库,提供了强大的序列化和反序列化功能。然而,当JSON结构与目标POJO的预期结构不完全匹配时,可能会遇到MismatchedInputException等错误。本文将详细解析一个常见场景:将一个直接由对象数组组成的JSON字符串反序列化到一个包含嵌套列表的POJO中,并提供多种解决方案。

理解JSON与POJO结构不匹配的问题

假设我们有一个JSON字符串,它是一个对象数组,每个对象包含name、number和age字段:

[    {        "name": "A",        "number": 1,        "age": 20    },    {        "name": "B",        "number": 2,        "age": 30    },    {        "name": "C",        "number": 3,        "age": 40    }]

我们期望将其反序列化到一个名为FooResClass的Java对象中,该对象内部包含一个AData类型的列表:

@Data@JsonIgnoreProperties(ignoreUnknown = true)public class FooResClass extends BaseResModel {    private List aDataList;    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    public class AData { // 注意:此处AData为非静态内部类        @JsonProperty("number")        private Long number;        @JsonProperty("name")        private String name;    }}

直接使用ObjectMapper尝试将上述JSON反序列化为FooResClass实例时,会抛出MismatchedInputException。这是因为:

立即学习“Java免费学习笔记(深入)”;

JSON根结构不匹配:提供的JSON是一个数组([开头),而FooResClass是一个Java对象,Jackson期望JSON的根是一个对象({开头),并且其中包含一个名为aDataList的字段来映射到FooResClass的aDataList属性。内部类AData的限制:AData作为FooResClass的非静态内部类,其实例化需要FooResClass的一个实例。Jackson在反序列化时无法独立实例化非静态内部类,这也会导致问题。为了让Jackson能够独立创建AData实例,AData必须声明为static内部类。

解决方案一:直接解析JSON数组到列表

如果JSON字符串本身就是一个列表,我们可以直接将其反序列化为Java的List类型,然后再手动构建FooResClass对象。

import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.Data;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import com.fasterxml.jackson.annotation.JsonProperty;import java.io.IOException;import java.util.List;public class JsonArrayToListExample {    // 确保AData是静态内部类,以便Jackson可以独立实例化    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    public static class AData {        @JsonProperty("number")        private Long number;        @JsonProperty("name")        private String name;    }    // 假设FooResClass有一个接收List的构造函数    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    // 假设BaseResModel存在且FooResClass继承它    // @EqualsAndHashCode(callSuper = true) // 如果需要    // @AllArgsConstructor // 如果需要有参构造器    public static class FooResClass { // FooResClass也应是静态类或顶级类        private List aDataList;        public FooResClass(List aDataList) {            this.aDataList = aDataList;        }    }    public static void main(String[] args) throws IOException {        String json = "[n" +                "    {n" +                "        "name": "A",n" +                "        "number": 1,n" +                "        "age": 20n" +                "    },n" +                "    {n" +                "        "name": "B",n" +                "        "number": 2,n" +                "        "age": 30n" +                "    },n" +                "    {n" +                "        "name": "C",n" +                "        "number": 3,n" +                "        "age": 40n" +                "    }n" +                "]";        ObjectMapper mapper = new ObjectMapper();        // 直接将JSON数组解析为List        List aDataList = mapper.readValue(json, new TypeReference<List>() {});        // 使用解析出的列表构建FooResClass实例        FooResClass fooRes = new FooResClass(aDataList);        System.out.println("解析成功,FooResClass实例: " + fooRes);        System.out.println("列表内容: " + fooRes.getADataList());    }}

优点:简单直接,适用于JSON结构本身就是目标列表的情况。缺点:需要手动构建外层对象,如果FooResClass有更多复杂逻辑,这种方式可能不够优雅。

解决方案二:调整JSON结构以匹配POJO

如果我们可以控制JSON的生成方,最直接的解决方案是修改JSON结构,使其与FooResClass的预期完全匹配。这意味着JSON应该是一个对象,其中包含一个名为aDataList的字段,其值是一个数组。

期望的JSON结构应如下所示:

九歌 九歌

九歌–人工智能诗歌写作系统

九歌 322 查看详情 九歌

{   "aDataList":[      {         "name":"A",         "number":1,         "age":20      },      {         "name":"B",         "number":2,         "age":30      },      {         "name":"C",         "number":3,         "age":40      }   ]}

在这种情况下,FooResClass的定义保持不变(确保AData是静态内部类),Jackson将能够自动完成反序列化:

import com.fasterxml.jackson.databind.ObjectMapper;import lombok.Data;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import com.fasterxml.jackson.annotation.JsonProperty;import java.io.IOException;import java.util.List;public class MatchedJsonStructureExample {    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    public static class AData {        @JsonProperty("number")        private Long number;        @JsonProperty("name")        private String name;    }    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    public static class FooResClass {        @JsonProperty("aDataList") // 确保字段名与JSON中的key匹配        private List aDataList;    }    public static void main(String[] args) throws IOException {        String json = "{n" +                "   "aDataList":[n" +                "      {n" +                "         "name":"A",n" +                "         "number":1,n" +                "         "age":20n" +                "      },n" +                "      {n" +                "         "name":"B",n" +                "         "number":2,n" +                "         "age":30n" +                "      },n" +                "      {n" +                "         "name":"C",n" +                "         "number":3,n" +                "         "age":40n" +                "      }n" +                "   ]n" +                "}";        ObjectMapper mapper = new ObjectMapper();        FooResClass fooRes = mapper.readValue(json, FooResClass.class);        System.out.println("解析成功,FooResClass实例: " + fooRes);        System.out.println("列表内容: " + fooRes.getADataList());    }}

优点:Jackson自动处理,代码简洁,符合POJO设计理念。缺点:要求修改JSON源,这在许多情况下可能无法实现。

解决方案三:实现自定义反序列化器 (推荐)

当无法修改JSON结构,又希望直接将JSON数组反序列化为包含嵌套列表的FooResClass实例时,自定义反序列化器是最佳选择。通过实现JsonDeserializer或继承StdDeserializer,我们可以完全控制反序列化过程。

首先,确保FooResClass和AData都是静态内部类,并且FooResClass有一个接收List的构造函数(或使用Lombok的@AllArgsConstructor)。

import com.fasterxml.jackson.annotation.JsonCreator; // 用于标记构造函数import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.databind.annotation.JsonDeserialize;import lombok.AllArgsConstructor; // 如果需要有参构造器import lombok.Data;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import java.util.List;// FooResClass 必须是静态的,如果它作为另一个类的内部类存在// 或者直接作为顶级类@Data@JsonIgnoreProperties(ignoreUnknown = true)@AllArgsConstructor // 为FooResClass提供一个接收List的构造函数@JsonDeserialize(using = FooResClassDeserializer.class) // 指定自定义反序列化器public static class FooResClass { // 确保是静态内部类或顶级类    private List aDataList;    @Data    @JsonIgnoreProperties(ignoreUnknown = true)    public static class AData { // 确保是静态内部类        @JsonProperty("number")        private Long number;        @JsonProperty("name")        private String name;    }}

接下来,创建FooResClassDeserializer,它将负责将JSON数组解析为List,然后用这个列表来构造FooResClass实例。

import com.fasterxml.jackson.core.JacksonException;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.deser.std.StdDeserializer;import java.io.IOException;import java.util.List;public class FooResClassDeserializer extends StdDeserializer {    public FooResClassDeserializer() {        this(null);    }    public FooResClassDeserializer(Class vc) {        super(vc);    }    @Override    public FooResClass deserialize(JsonParser p,                                   DeserializationContext ctxt) throws IOException, JacksonException {        ObjectMapper mapper = (ObjectMapper) p.getCodec(); // 获取当前的ObjectMapper实例        // 将整个JSON输入(它是一个数组)解析为List        List aDataList = mapper.readValue(p, new TypeReference<List>() {});        // 使用解析出的列表构建FooResClass实例        return new FooResClass(aDataList);    }}

最后,在使用ObjectMapper进行反序列化时,Jackson会自动查找@JsonDeserialize注解并使用指定的反序列化器。

import com.fasterxml.jackson.databind.ObjectMapper;import java.io.IOException;public class CustomDeserializerExample {    public static void main(String[] args) throws IOException {        String json = "[n" +                "    {n" +                "        "name": "A",n" +                "        "number": 1,n" +                "        "age": 20n" +                "    },n" +                "    {n" +                "        "name": "B",n" +                "        "number": 2,n" +                "        "age": 30n" +                "    },n" +                "    {n" +                "        "name": "C",n" +                "        "number": 3,n" +                "        "age": 40n" +                "    }n" +                "]";        ObjectMapper mapper = new ObjectMapper();        // Jackson将使用FooResClass上指定的FooResClassDeserializer        FooResClass fooRes = mapper.readValue(json, FooResClass.class);        System.out.println("解析成功,FooResClass实例: " + fooRes);        System.out.println("列表内容: " + fooRes.getADataList());    }}

优点:高度灵活,能够处理各种不匹配的JSON结构,无需修改JSON源。将反序列化逻辑封装起来,提高了代码的可维护性。缺点:增加了代码量和复杂性,需要编写额外的反序列化器类。

注意事项与总结

静态内部类:无论是哪种解决方案,如果AData是FooResClass的内部类,它都必须声明为static。否则,Jackson无法在没有外部类实例的情况下创建AData的实例。@JsonIgnoreProperties(ignoreUnknown = true):这个注解非常有用,它告诉Jackson忽略JSON中存在但POJO中没有定义的字段,避免因字段不匹配而抛出异常。Lombok注解:@Data简化了getter/setter、equals、hashCode和toString方法的生成。@AllArgsConstructor可以方便地为所有字段生成构造函数,这在自定义反序列化器中非常有用。TypeReference:在反序列化泛型类型(如List)时,需要使用TypeReference来帮助Jackson获取正确的泛型类型信息。

总而言之,处理JSON数组到包含嵌套列表的Java对象反序列化问题,关键在于理解JSON与POJO之间的结构差异。当JSON结构与POJO预期不符时,我们可以选择直接解析为列表后手动构建,或者在能控制JSON源的情况下调整JSON结构。而当这些方法不可行时,自定义反序列化器提供了一个强大且灵活的解决方案,能够优雅地桥接JSON与POJO之间的差异。选择哪种方法取决于具体的需求、JSON源的可控性以及对代码复杂度的接受程度。

以上就是Jackson反序列化:处理JSON数组到嵌套List的Java对象映射的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1070157.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 06:34:44
下一篇 2025年12月2日 06:35:05

相关推荐

  • Web3板块有哪些币_Web3板块龙头币种盘点

    Web3板块的核心币种包括:1. 底层公链与基础设施中的以太坊(ETH)、波卡(DOT)、Solana(SOL);2. 去中心化存储中的Filecoin(FIL)、Arweave(AR)。 Web3被视为互联网的下一代形态,其核心理念是去中心化、用户自主权和基于区块链的价值网络。在这个生态系统中,涌…

    2025年12月8日
    000
  • 大白话讲什么是web3 人人都能看懂的web3

    Web3的核心是让用户真正拥有自己的数据和资产,1. Web1只能读,信息单向传播;2. Web2可以读和写,但平台控制一切;3. Web3通过区块链技术实现去中心化,使用户能读、能写、更能拥有,数据由个人掌控,资产安全不可篡改,隐私更强,交易去中介化,应用无法被单方面关闭,最终将互联网的权力归还用…

    2025年12月8日
    000
  • 2025年Web3趋势预测:哪些赛道值得提前布局?新手必看

    2025年Web3将迈向大规模落地,新手应重点关注四大核心赛道并遵循四步安全布局策略。 随着区块链技术的不断成熟和应用场景的持续拓展,Web3正在从概念炒作阶段迈向大规模应用的落地期。2025年,我们将见证更多创新与融合,对于希望进入这个领域的新手来说,提前了解并布局关键赛道至关重要。以下是对202…

    2025年12月8日
    000
  • Codatta(XNY币)是什么?XNY代币经济学、价格预测介绍

    Codatta 是什么?解决 AI 时代的核心痛点 Codatta 定位于 AGI(通用人工智能)的可扩展数据通道,利用区块链技术打造去中心化数据协议。它连接数据提供者与 AI 开发者,将原始信息转化为可验证、可资产化的数据资源,直面传统中心化数据市场的四大难题: 数据溯源困难:无法确认来源与真实性…

    2025年12月8日
    100
  • 以太坊交易员预计ETH价格将在本周期达到1.6万美元

    目录 要点摘要:以太坊技术面暗示ETH价格或将冲击五位数现货以太坊ETF持续18日资金净流入 ‍以太坊正构筑一个上升三角形突破结构,潜在价格目标指向约16,700美元。 要点摘要: 尽管以太坊在4,000美元区域遭遇阻力,但强劲的技术信号与不断上升的机构兴趣可能推动ETH进入新一轮价格发现阶段。上升…

    2025年12月8日 好文分享
    000
  • 什么是OLAXBT(AIO币)?值得投资吗?OLAXBT项目概述,代币经济,前景分析

    目录 OLAXBT项目定位OLAXBT核心技术OlaXBT最新动态AIO代币经济代币分配解锁时间表代币效用OLAXBT生态进展OLAXBT风险管理与应对措施OLAXBT未来规划常见问题总结 olaxbt(aio)是一款将 ai 驱动的量化策略与去中心化交易协议结合的 web3 平台,旨在通过预制与自…

    2025年12月8日 好文分享
    000
  • 以太坊(ETH)衍生品缺乏动力,引发对冲击4000美元反弹的质疑

    目录 要点摘要:ETH交易者情绪低迷,因以太坊TVL下滑 ‍尽管etf资金持续流入,但由于竞争加剧与链上活动乏力,eth市场参与者仍保持谨慎。 要点摘要: 尽管ETH价格反弹且ETF资金流入强劲,衍生品数据表明交易者情绪仍偏保守。以太坊面临来自Solana和BNB Chain的竞争压力,同时自身网络…

    2025年12月8日 好文分享
    000
  • Layer2 混战再起:Linea 代币上线,是机会还是鸡肋?

    备受关注的以太坊二层网络Linea终于正式推出其原生代币。 根据项目团队发布的最新公告,我整理出一些对普通用户尤为重要的信息点: – 代币总供应量约为720亿枚– 其中9%将通过空投形式发放给早期用户…… 目前,LINEA代币在系统中尚未赋予具体用途,既不作为交易手续费支付(…

    2025年12月8日
    000
  • 以太坊十周年:7 大维度揭秘为何 ETH 涨势才刚开始?

    一、ETH储备概念股 近期以太坊市场买气旺盛,多家上市公司与资产管理机构纷纷增持,甚至将ETH纳入核心财务战略。与此同时,ETH储备相关概念股在美股市场表现抢眼,成为资本新宠。 华尔街知名策略师、Fundstrat联合创始人Thomas Lee的动向成为关键催化剂。他于2025年出任Bitmine董…

    2025年12月8日 好文分享
    000
  • 2025山寨币投资指南:哪些关键指标值的关注?

    目录 叙事与市场契合度及高关注度增长的指标合理的Token经济学 即将解锁的token Token效用 以社区为中心的理念 总结 牛市行情回来了(至少目前看来如此)。 但关键问题是:哪些山寨币最有可能成为本轮周期中的领跑者? 回顾2021年的牛市,几乎任何项目都能迎来大幅上涨。然而,时过境迁,如今市…

    2025年12月8日
    000
  • Kraken即将IPO上市,有哪些标的可以炒作?

    Pre-IPO 投资热潮来袭,散户也能抢跑上市前 随着 OpenAI、SpaceX 等顶尖科技企业长期保持私有状态,大量早期员工与投资人希望在正式IPO前实现股权变现。而 Forge 正是连接“出售方”与“提前布局投资者”的关键平台。当前 Kraken 上市预期持续升温,一旦其内部股东或机构开始释放…

    2025年12月8日 好文分享
    000
  • XRP价格预测:XRP可能正准备展开下一波牛市

    XRP或迎来新一轮上涨周期,近期走势为看涨预测提供了技术支撑。 在7月中旬经历约20%的回调后,XRP价格在2.90美元区域展现出强劲支撑,构筑出双底结构。这一经典技术形态通常预示趋势反转,暗示市场买盘正在回归。 然而,整体宏观环境仍存不确定性。美联储7月选择暂停加息,采取观望策略,同时新关税政策引…

    2025年12月8日 好文分享
    000
  • ATOR Protocol(ATOR币)是什么?ATOR币未来前景及价格分析

    目录 什么是ATOR协议?ATOR协议的特点白名单访问和质押匿名性ATOR协议(ATOR)的用途是什么?什么是ATOR代币?ATOR Protocol如何运作?Airtor Protocol (ATOR)特点ATOR币未来前景如何?技术前景市场前景应用前景ATOR币是一项好的投资吗?ATOR Pro…

    2025年12月8日
    000
  • InterLink(ITLG币)是什么?值得投资吗?ITLG代币经济学和未来展望

    目录 项目定位是什么? 核心技术的关键特点是什么? InterLink 的 ITLG 代币经济学:它是如何设计的? 代币实用程序: 迄今为止生态系统进展如何? InterLink 如何管理风险和应对挑战? InterLink 的未来计划是什么? 常问问题 关键要点 InterLink 致力于构建全球…

    2025年12月8日
    000
  • 以太坊(Ethereum)研究员提出“精简”网络应对量子时代

    以太坊基金会研究人员Justin Drake近日提出名为“精简以太坊”(Slim Ethereum)的新倡议,目标是提升以太坊主网的速度与量子抗性,同时大幅降低其底层技术架构的复杂度。 该计划聚焦于重构以太坊的三大核心层级:共识层、数据层和执行层。Drake建议引入一种基于零知识证明的虚拟机,能够在…

    2025年12月8日
    000
  • MoMo.fun(MM币)是什么?是一个好投资吗?MM币价格预测与空投领取指南

    目录 MOMO.FUN是什么MOMO.FUN核心功能与优势AI Agent:智能化的核心驱动力AI Pool:智能化的募资与流动性管理Eliza 框架:链上链下的智能交互桥梁MemeFi 模式:打造 Meme + DeFi 的完美结合MOMO.FUN空投领取MM币价格预测Momofun 2025 年…

    2025年12月8日
    000
  • 山寨币季节指数 2025年:一文预测加密货币市场的繁荣

    目录 山寨币季节指数解析:交易者的关键指标山寨币指数如何运作:计算 2025 年的市场变化过去的山寨币季节:从以往的加密货币市场周期中吸取的教训加密货币市场趋势:过去山寨币季度指数数据的关键洞察2025 年山寨币季节即将来临,主要指标如何利用指数判断山寨币旺季何时开始?比特币主导地位 vs. 山寨币…

    2025年12月8日
    000
  • 欧易okx交易平台官方版App注册入口 欧易官方app安装注册下载链接及步骤汇总

    欧易OKX交易平台是一款全球领先的数字资产交易应用,提供现货交易、合约交易、理财等多种服务。本文为您准备了欧易官方App下载入口,用户只需点击本文提供的官方链接即可快速下载安装,安全开启数字货币交易体验。为了帮助新用户顺利完成安装与注册,下面将详细介绍完整步骤。 下载安装步骤 1、点击本文提供的,进…

    2025年12月8日 好文分享
    000
  • 欧易交易所APP安卓版 v6.132.0 欧易APP官网下载安装指南2025

    欧易(OKX)是一款全球知名的数字资产综合服务平台,为广大用户提供涵盖现货、合约、期权等在内的多元化产品和服务。其官方APP凭借流畅的操作体验和强大的功能集成,成为了许多数字资产用户的常用工具。 本文为您整理了欧易交易所app安卓最新版的官网下载安装指南,点击本文中提供的官方下载链接,即可安全快速地…

    2025年12月8日 好文分享
    000
  • oyi交易所app安卓下载链接 欧意交易平台官方app手机端详细安装注册教程

    欧易交易所是一款全球领先的数字资产交易平台,为用户提供多样化的数字货币交易服务。本文将为您提供欧易交易平台安卓手机端网址,点击本文中的下载链接即可轻松下载安装。下文还将详细介绍安装和注册的具体流程,帮助您快速开启数字资产交易之旅。 欧易App下载与安装步骤 1、点击本文提供的 ,系统会自动开始下载。…

    2025年12月8日 好文分享
    000

发表回复

登录后才能评论
关注微信