V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Nitroethane
V2EX  ›  Android

关于 Gson 解析 json 数据

  •  1
     
  •   Nitroethane · 2019-04-28 23:35:56 +08:00 · 10683 次点击
    这是一个创建于 2038 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现有服务端返回的数据格式如下:

    {
      "success": true,
      "data": [
        {
          "label": "高清频道",
          "id": 1,
          "expanded": false,
          "children": [
            {
              "label": "CCTV1 综合高清",
              "id": 1,
              "actionUrl": "/tv-show-detail/1",
              "imgUrl": "/cover/tv/1.jpg",
              "current": {
                "name": "瞬间中国",
                "time": "15:15-15:23"
              }
             },
            {
              "label": "CCTV2 财经高清",
              "id": 2,
              "actionUrl": "/tv-show-detail/2",
              "imgUrl": "/cover/tv/2.jpg",
              "current": {
                "name": "周末特供",
                "time": "15:20-15:42"
              }
             },
            {
              "label": "BTV6 体育高清",
              "id": 19,
              "actionUrl": "/tv-show-detail/19",
              "imgUrl": "/cover/tv/19.jpg",
              "current": false
             }
           ]
         }
       ]
    }
    

    children 字段里元素对应的类的定义为(使用的 Retrofit 和 Gson ):

    public class Channel {
        @SerializedName("label")
        private String label;
        @SerializedName("id")
        private int id;
        @SerializedName("actionUrl")
        private String actionUrl;
        @SerializedName("imgUrl")
        private String imgUrl;
        @SerializedName("current")
        private CurrentShow current;
        ......
    

    CurrentShow 是我定义的用来解析 current 字段的:

    public class CurrentShow {
        private String name;
        private String time;
        private boolean empty;
        ...
    

    现在的问题是,如果 current 字段为空的话值是 false,否则是 nametime 字段,所以上面这个 CurrentShow 用来处理 current 字段是有问题的。这个应该怎么处理呢?

    26 条回复    2019-04-30 08:39:52 +08:00
    MonoLogueChi
        1
    MonoLogueChi  
       2019-04-28 23:52:45 +08:00 via Android
    把 false 当作 null 来处理?只是我猜的
    AngryMagikarp
        3
    AngryMagikarp  
       2019-04-28 23:57:53 +08:00
    你们这个接口数据不规范。current 怎么可以同时是两种数据类型,在这里既有可能是 Object,也可能是 boolean。这是不规范的做法。

    如果是 Object,那么它的空值就是 null,不是 false。

    如果确实需要一个 boolean 字段,应该和 current 分开,再加一个字段。
    AngryMagikarp
        4
    AngryMagikarp  
       2019-04-28 23:59:35 +08:00
    这种格式不仅是 GSON,大部分语言的 JSON 解析库都会错。
    maninfog
        5
    maninfog  
       2019-04-29 00:02:08 +08:00 via iPhone
    我猜你们的后台是 php ?
    Nitroethane
        6
    Nitroethane  
    OP
       2019-04-29 00:10:28 +08:00 via Android
    @AngryMagikarp 接口数据是不规范...
    @maninfog 我是给一个 Web 应用做一个 Android 客户端,算是个人项目,不是公司项目。后台不知道用啥写的......
    @MonoLogueChi 刚开始的想法是打算当作 null 处理,但不知道咋操作...
    AngryMagikarp
        7
    AngryMagikarp  
       2019-04-29 00:12:34 +08:00
    @Nitroethane 给你想个投机取巧的方法,解析之前把所有

    "current": false 替换成 "current": null
    MonoLogueChi
        8
    MonoLogueChi  
       2019-04-29 00:26:09 +08:00 via Android
    @Nitroethane Java 我不太懂,反正我知道某些库在解析失败的时候可能会是 null,但是不推荐这样做,如果是 C#的话我知道应该怎么做
    helloworld000
        9
    helloworld000  
       2019-04-29 01:05:43 +08:00
    为什么不用 protobuf ?
    kevinlm
        10
    kevinlm  
       2019-04-29 04:40:40 +08:00 via iPhone
    jsonobject 类型判断吧。一般这样的,确实只有 php 能干的出来,简直就是业界毒瘤
    alphatoad
        11
    alphatoad  
       2019-04-29 05:04:17 +08:00 via iPhone
    Protobuf,请
    MoHen9
        12
    MoHen9  
       2019-04-29 08:31:28 +08:00 via Android
    自定义解析器,你到网上随便搜一下就有

    PHP 可能自动隐式转换了
    ragnaroks
        13
    ragnaroks  
       2019-04-29 08:36:06 +08:00
    php 天下第一!

    什么,你要我和 php 后端对接?溜了溜了
    Jrue0011
        14
    Jrue0011  
       2019-04-29 09:15:20 +08:00
    GSON 应该可以单独为这个字段自定义一个处理器?
    abbenyyy
        15
    abbenyyy  
       2019-04-29 09:50:55 +08:00
    后端是真毒瘤,特别是这段时间培训班出来的 Java 也喜欢这么干。提个不太优雅的 Android 端处理方案吧,current 用 object 解析,之后要用到 current 的时候再强转。
    TommyLemon
        16
    TommyLemon  
       2019-04-29 09:56:44 +08:00
    类型不稳定是接口大忌,要么你说服后端改,要么自己兼容,
    简单的方法是 current 类型定义为兼容两者的 Object,然后
    if (current instanceof JsonObject) {
    JsonObject cur = (JsonObject) current;
    ...
    }
    else if (current instanceof Boolean) {
    Boolean cur = (Boolean) current;
    ...
    }
    else {
    ...
    }
    TommyLemon
        17
    TommyLemon  
       2019-04-29 09:58:25 +08:00
    不过这种情况我也是见过很多次了,头疼,所以写了一个开源库,彻底解决

    点 Star 支持下吧 ^_^
    https://www.v2ex.com/t/559388
    gaius
        18
    gaius  
       2019-04-29 10:00:24 +08:00
    全替换成 null 省事
    rookiewhy
        19
    rookiewhy  
       2019-04-29 10:13:12 +08:00
    php 吧,现在的后端就是 php,经常会有这种问题,我都是给坚持 json 数据应该按照规范来。
    CononYc
        20
    CononYc  
       2019-04-29 10:53:18 +08:00
    把 current 换成 object 类型把,然后循环的时候再去判断 current 的类型是不是布尔类型,做对应的处理
    TommyLemon
        21
    TommyLemon  
       2019-04-29 11:02:41 +08:00
    @CononYc 对的,我在 #16 楼也说了,还提供了代码
    LemonCoo1
        22
    LemonCoo1  
       2019-04-29 11:18:27 +08:00
    @abbenyyy java 想这么写还挺难的吧,都是定义好的类型怎么又是 boolean 又是 object,除非你直接用 jsonobject、map 啥的
    TommyLemon
        23
    TommyLemon  
       2019-04-29 14:34:54 +08:00
    @LemonCoo1 是的,静态类型定义好就不好改了,这个约束对前端是很利好的,如果还会变,只能说后端故意的。
    APIJSON 很好地解决了类型不稳定等 前后端接口的 沟通、文档、联调 10 大痛点哦。

    Node.ts, Python, PHP, Java, C#, Go 等多种语言后端实现,Android, iOS, JavaScript 等多端的 Demo,
    还有各种文档、视频教程、在线工具等。

    创作不易,GitHub 右上角点 Star 支持下吧 ^_^
    https://github.com/TommyLemon/APIJSON/wiki
    TommyLemon
        24
    TommyLemon  
       2019-04-29 14:36:13 +08:00
    TommyLemon
        25
    TommyLemon  
       2019-04-29 14:36:40 +08:00
    @TommyLemon #23 楼给了很好的解决方案哦
    RockOrRoll
        26
    RockOrRoll  
       2019-04-30 08:39:52 +08:00 via Android
    @TommyLemon 消停点吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2240 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 16:12 · PVG 00:12 · LAX 08:12 · JFK 11:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.