公司后台程序员,返回了一种让我讨厌的 Json

↓推荐关注↓

前言

JSON转Model,明明是个机械活,但是有的时候后台给的接口文档,就是转不出正确的模型,是一件让人非常窝火的事情。

错无非两种,要么后台文档给的有错,要么自己写的有错。

在经受过多次跳坑与爬坑的经历后,我变秃了,也变强了。

今天说说我遇见最讨厌的一种JSON,就是JSON中嵌套JSON String

后台文档的不给力

事情一开始是这样的,后台给我文档,说请求响应的JSON长这个样子:

{
    "result":true,
    "body":{
        "ret_code":"0",
        "ret_msg":"成功",
        "serial_number":"20211002115646portal511788",
        "timestamp":"2021-10-02 03:56:46",
        "response_data":{
            "token":"0765499c-8643-4491-8c8e-50f92a2ea004",
            "expiredMills":1633751806616
        }
    }
}

我心想,这有何难,工具一键生成代码,请求转换就好了嘛:

// MARK: - Token
struct Token: Codable {
    let result: Bool?
    let body: Body?
}

// MARK: - Body
struct Body: Codable {

    let retCode: String?
    let retMsg: String?
    let serialNumber: String?
    let timestamp: String?
    let responseData: ResponseData?

    enum CodingKeys: String, CodingKey {
        case retCode = "ret_code"
        case retMsg = "ret_msg"
        case serialNumber = "serial_number"
        case timestamp = "timestamp"
        case responseData = "response_data"
    }
}

// MARK: - ResponseData
struct ResponseData: Codable {
    let token: String?
    let expiredMills: Int?
}

由于项目比较老,还是用的Alamofire4,请求与转换:

func getToken() {
    Alamofire.request("请求网址", method: .post).responseData { response in

        switch response.result {
        case .success(let data):

            guard let model = try? JSONDecoder().decode(Token.self, from: data) else {
                return
            }

            print(model)

        case .failure(_):
            break
        }
    }
}

然后就在.success中的guard let这里return了,我反复看了文档,然后又看了定义的Model,感觉没错啊,也走到success里了,data也有值啊,怎么回事呢?

所幸先把data转成Dictionary看看再说,顺带在postman里请求看看,JSON到底是啥:

{
    "result": true,
    "body": "{\"ret_code\":\"0\",\"ret_msg\":\"成功\",\"serial_number\":\"20211002115646portal511788\",\"timestamp\":\"2021-10-02 03:56:46\",\"response_data\":{\"token\":\"0765499c-8643-4491-8c8e-50f92a2ea004\",\"expiredMills\":1633751806616}}"
}

结果这个一个JSON中包裹JSON String。

JSON中包裹JSON String解析

这种JSON中包裹JSON String解析非常的麻烦:

  • 首先Model的结构要重新定义。

  • 要多写一些代码去做处理。

然后大概就变成了这样,这里贴出关键代码:

struct Token: Codable {

    let result: Bool?
    
    /// body变成了String
    let body: String?

}

转换多了几步:

guard let model = try? JSONDecoder().decode(Token.self, from: data) else {
    return
}

guard let string = model.body else {
    return
}

guard let stringData = string.data(using: .utf8) else {
    return
}

guard let body = try? JSONDecoder().decode(Body.self, from: stringData) else {
    return
}
  • 首先转成Token模型。

  • 再拿Token实例中的body,这个body是个String。

  • 然后body转为stringData。

  • 最后stringData最后转成Body的Model。

你说累不累?

看着这个头大的转换,我就想有没有更简洁的方式。

注意,这里其实可以将多个guard写成一个guard,不断let即可,我没有这么写是为了方便调试。

Response全部转String,再转Data,最后转Model的尝试

我想到了Alamofire中有一个responseString方法,我想到了这样一个思路:

c51145ac0f79ba702ec35bf3be6098e8.png

于是我试了试:

struct Token: Codable {

    let result: Bool?
    
    /// body试着用Body去接收
    let body: Body?

}
func getToken() {

    Alamofire.request("请求网址", method: .post).responseString( encoding: .utf8) { res in

        switch res.result {

        case .success(let string):
            guard let stringData = string.data(using: .utf8) else {
                return
            }

            guard let model = try? JSONDecoder().decode(Token.self, from: stringData) else {
                return
            }

            print(model)

        case .failure(_):
            break
        }
    }
}

不过尝试的结果是让人失望了的,在这一步就return了:

guard let model = try? JSONDecoder().decode(Token.self, from: stringData) else {
    return
}

转换成为响应体中的String没有问题,String转Data也没有问题,但是Data转Model就出错了。

所以说这种JSON中包裹JSON String的返回真的很难办啊!

最好的方式其实是和后台沟通

既然自己App端干这JSON转Model的事情吃力不讨好,最快最简洁的方式就是和后台沟通,让他们把这个JSON String转成JSON再塞到这个母JSON中,可以采取的措施有以下几点:

  • 后台给出的文档与实际的返回有出入,要么改文档,要么改Response。可是一般程序猿不喜欢改文档。

  • 返回JSON String不合符Response返回的规范,也不安全。

  • 拉着Android端的同学一起去找后台,人多力量大。

  • 反馈到技术经理,让他去定夺。

  • 不要相信后台说后续优化,要么现在改,要么就不改,否则自己下次还是得删改代码。

总结

上面吧嗒吧嗒说了一大堆,怎么处理JSON啊,各种思路啊。

其实归结到最后,如果能和后台沟通好这件事情,自己可能处理起来就会轻松不少。程序猿有的时候只会站在自己的视角去解决问题,有的时候,跳出来,弄清楚原因找到根节,事情就会变得简单不少。

转自:掘金 season_zhu

https://juejin.cn/post/7022130994241077256

 
 

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

 
 

 关注公众号:Java后端编程,回复下面关键字 

 
 

要Java学习完整路线,回复  路线 

缺Java入门视频,回复: 视频 

要Java面试经验,回复  面试 

缺Java项目,回复: 项目 

进Java粉丝群: 加群 

 
 

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

 
 

(完)

加我"微信" 获取一份 最新Java面试题资料

15e14f2131254468589193cc9c2cae34.png

请备注:666,不然不通过~

最近好文

1、Kafka 3.0重磅发布,弃用 Java 8 的支持!

2、你只会用 ! = null 判空?嘿嘿!

3、这次,Swagger-ui遇到对手了!

4、上午写了一段代码,下午就被开除了...

5、抖音项目Semi Design涉嫌抄袭?技术团队发文致歉!

 
 

508c759d8dc56b109ec232d610a34e5e.png

 
 
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值