java对象与json,string 之间复杂转换(抽丝剥茧的完成数据解析详解)

因为最近公司业务需求,需要两个平台之间的交互,所以大量的接口编程。重点是数据格式的不统一,所以在传输过程中遇到了不少对象转换的问题。
又因为都是json的形式传递数据,所以主要问题也就是json字符串和string,map,list,java对象中间的来回转化。
在这特意写个帖子记录下来中间遇到的问题和解决办法,其实说起来一点也不高深莫测,但是浅显却又复杂,一不小心就容易出个错。这个帖子也算是给自己的自己做一个提示吧。
首先导入依赖:

        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

String转换成java对象

因为是交互,所以是双方都要提供接口的,其实有一个接口我希望的参数是一个对象,并且我在controller中用@RequestBody注释过了参数(spring boot项目),但是在测试中同事表示调不通这个接口,严厉要去我改成string的形式接受参数,据说是对象无法传输(因为手头忙加上别人的意见,我也懒得看为什么对象传不过来了,只能表示呵呵并且将参数改为string)。
然后涉及到的就是我需要把这个string参数解析成一个对象。

  • 首先第一步:把object转换成jsonObject。
    因为我这里想把string类型转换jsonObject,所以这个参数就是string类型的。
    这个方法是net.sf.json.JSONObject包中的,参数类型就是Object。
        JSONObject jsonObject = JSONObject.fromObject(object);
  • 第二步:将jsonObject转换成对象。
    如图所示吧,这个BaseCar是我自己定义的类,用JSONObject.toBean转化,第一个参数是jsonObject,第二个参数是想转化的类。
BaseCar baseCar = (BaseCar) JSONObject.toBean(jsonObject, BaseCar.class);

这里的转化容易遇到问题,尤其是我这种,只能根据格式来创建接受类的,经常因为一个int和string,一个double和Long的不同,分分钟烦死个人呦,我当时是打个断点一遍遍走,哪个属性没转化成功然后改哪个属性才跑完的。
需要注意的就是这个数据类型真的要求挺严格的,不过稍微好一点的就是报错也很明显,很容易知道是哪个属性出的问题。
至此,一个最简单的字符串转化成java对象就完成了。

复杂嵌套层层转化

刚刚说的String转换成java对象是最简单的一种转化,因为直观而且只有一层,真正复杂的是N层嵌套的转化、比如我从同事接口那获取来的数据。
因为涉及到公司数据,所以在这不截图显示了。简单画一个数据结构图,这个真的是简化简化再简化之后的了。反正对付看吧。


数据结构

然后我以一个下午的手忙脚乱心烦意燥的经验提醒大家:
遇到这种数据结构千万别着急,一定要一层一层理清楚了再做。不然想要一口吃成胖子或者说一次性解析成功真的要拼脸了。
然后我这里也会一步一步的解析并且附上一些容易出错的点和我犯过的错误。

  1. result.getStatusCodeValue() == 200
    需要注意的是这个是第一步,也是最基本的一步:判断接口调用是不是成功了!这个不同于你们前后端约定好的200,300或者500等状态,这个是接口调用的返回值,换言之只要你正常的访问了接口,哪怕得到的返回值是300,500那也是一次成功的访问,所以这个result.getStatusCodeValue()也会是200.但是假如接口访问失败,服务端没有起这个接口,或者接口路径写的有问题等等,就会出现各种各种的StatusCodeValue值了,所以我们解析的前提就是这个访问是正常的成功的!也就是以下的所有解析代码都要在
if(result.getStatusCodeValue() == 200)

这个前提下使用。

  1. map.get("status")==200
    刚刚的数据结构我已经大概画出来了,显而易见也是以键值对的形式存放的,所以我这里如果访问正常就会以map的形式解析
                // 将json转化成java数组对象的工具类
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> map = mapper.readValue(result.getBody(), Map.class);

这个result.getBody()是指接口的具体返回数据。将此数据用map解析。key如图所示分别是status,data,message.......(我为了简化只写了这几个)
然后我这里的第二步,判断map.get("status")是不是等于200.这个是接口定义的。如果不是二百说明访问有问题,所以不用再往下解析data了。同理是200则正常解析。一句话总结,再往下的解析代码要在

if(map.get("status")==200)

这个前提下使用。

  1. 多层解析
    这个其实很明显,我这个对象里有data,data里还是map形式的user,car....等等,所以还是以map解析
Map<String, Object> map = mapper.readValue(map.get("data"), Map.class);

这里的要注意的点就是多层解析就有多个map实体,反正我之前因为做的心浮气躁的就犯了低级错误,map,map1,map2之类的用混了,最终导致结果错误,要不是断点调试估计肉眼看得看好久能找出来。建议大家别和我一样取名偷懒,每个map的名字写的见名知意一点,要么就是细心专心,我当时因为手头有别的事几个接口写的断断续续的,所以低级错误贼多,现在都心疼和我调试的同事。
继续往下,可以看到data里面的map的key就是car,user之类的,而value则是list。我们根据map的解析继续:

List<Object> list = (List<Object>) map.get("user");

这里注意,因为list里面的格式不定,所以我用Object来接收,这样也避免类型转换的错误。(这里的user是我瞎编的,所以我实际对象不是这么简单的)
同样道理,这里如果要解析的对象很多,list会有很多的话,最好也不要学我一开始list,list1,list2,list3,用着用着就乱了,我这都是血一般的教训。
下面截图是我们接口中的使用,因为涉及一些字段和对象的名字都打了马赛克,反正我是第一遍的接口写的随意但是问题较多,直接就都删了重新写的,条条理理都写的清楚了,往下的逻辑也好写。
而且我这里解析到这步,有的list直接就是对象,就是list里是又套了一层map,所以解析格式不太一样。


解析list

反正不管怎么说,解析到这里离我们的最终目的又进了一步了!接着如果我们解析出来的是list<Object>,则直接遍历list,将object转换成对象即可。
不过这里也涉及到你想将Object转换成什么,因为我这里的数据是创建了一个实体来接收,所以这个可以简单看成Object转换成java对象,和我们一开始说的那个方法是一样的写法:

        JSONObject jsonObject = JSONObject.fromObject(object); // 将数据转成json字符串
        BaseDriver baseDriver = (BaseDriver)JSONObject.toBean(jsonObject, BaseDriver.class);

如果我们这个是用List<Map<String,Object>>来接收的,那么只要遍历list解析map就好了。对了,还要讲这里遇到的一个有趣的问题,就是我同事这里,在这个map里以json字符串的形式给我传了其中一个对象(我也不知道为啥一个简单的接口,里面的数据格式乱七八糟的啥都有,反正这就是考研吧~只能接受啊),反正第一步都是遍历map:

                if (list != null && !list.isEmpty() && list.size() != 0) {
                    for(Map<String, String> map1 :list){
                        Object object = map1.get("buEntrust");
                        JSONObject jsonObject = JSONObject.fromObject(object); // 将数据转成json字符串
                        // 将json转换成对象
                        BuEntrust buEntrust = (BuEntrust) JSONObject.toBean(jsonObject, BuEntrust.class);

至此就算解析完了吧,手头有点事,先草草结尾,有啥问题的或者用了报错的欢迎提问,我看到了尽量会回复,私信留言都可以。
全文手打这么不容易的写个文如果你觉得用到了理解了留个言点个赞转个发什么的啊

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容