Java 动态解析对象很难吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
serge001
V2EX    Java

Java 动态解析对象很难吗?

  •  
  •   serge001 2020-02-16 09:00:12 +08:00 6514 次点击
    这是一个创建于 2072 天前的主题,其中的信息可能已经有所发展或是发生改变。

    接口返回的是 json 对象,结构大致如下:

    { extra: { key1: value1, key2: value2 } }

    extra 字段是固定的, 但是 key1 和 key2 是运营在后台配置的,安卓客户端拿到接口返回的对象后需要解析出来 key1 和 key2 上报到服务器, 但是安卓客户端同事说无法做这样的动态解析,或者很麻烦,解决方案就是固定 key1 和 key2,或者改变数据结构.

    我是前端,这个对于 js 来说就是一个解构符的事情,为什么对于 java 来说这么难呢?

    第 1 条附言    2020-02-16 13:02:26 +08:00
    接口这样设计确实不够合理,但是也是没办法,因为这个接口已经比较久了,前端别的地方已经用了,现在是安卓端要接入,其次后端比较强势
    38 条回复    2020-03-14 17:10:34 +08:00
    ewBuyVmLZMZE
        1
    ewBuyVmLZMZE  
       2020-02-16 09:04:42 +08:00   2
    这个不难的,这种结构,一个 Map 就解决了。

    ```java
    @Data
    public class JsonObject {
    private Map<String, String> extra;
    }

    ```
    manami
        2
    manami  
       2020-02-16 09:07:06 +08:00 via Android
    不难。可以先把 json 转 list,然后动态解析取值就很简单了
    manami
        3
    manami  
       2020-02-16 09:10:47 +08:00 via Android
    @manami 还是楼上转 map 方便……
    SakuraOjosama
        4
    SakuraOjosama  
       2020-02-16 09:13:01 +08:00
    倒是不难,无非就是这边遍历一下,
    用 JSONObject 会容易点,用 Gson 的话就。。。
    zy445566
        5
    zy445566  
       2020-02-16 09:31:09 +08:00 via Android
    一个是裹脚布,一个是火葬场。五十笑一百了
    zy445566
        6
    zy445566  
       2020-02-16 09:32:56 +08:00 via Android
    如果 value1 和 value2 类型还不固定,Map 用个锤子
    xxoolltt
        7
    xxoolltt  
       2020-02-16 10:07:04 +08:00 via iPhone
    json ?
    serge001
        8
    serge001  
    OP
       2020-02-16 10:17:12 +08:00
    @zy445566 类型固定为字符串
    hhhsuan
        9
    hhhsuan  
       2020-02-16 10:20:23 +08:00
    不管难不难,最好都别这么写,破坏了语义。
    rockyou12
        10
    rockyou12  
       2020-02-16 10:34:39 +08:00
    会影响数据结构与 json 解析效率,但一般 map 就可以解决。实在不行还可以用 jackson 里的 jsonnode 这种 api,但固定字段才是比较好的做法
    zzzmode
        11
    zzzmode  
       2020-02-16 10:39:18 +08:00
    解析没问题,考虑的是代码逻辑怎么上报,这种没法需要区分 key1 和 key2 的代表的含义
    yiqunz
        12
    yiqunz  
       2020-02-16 10:40:30 +08:00
    楼主是不是没说明白什么叫 key1,key2 不固定
    不固定能否枚举?还是 value 性质的 key ?
    能枚举那是正常情况应该不会有这种疑问,估计是不能枚举?
    value 性质的 key 这样设计我忍不了。。。如果 key 需要逻辑处理代码风格会不忍直视。。。

    那么问题来了:为什么 key 不固定?能否固定?
    jinhan13789991
        13
    jinhan13789991  
       2020-02-16 10:43:48 +08:00 via Android   3
    { extra: [{ name:key1,value:value1 },{name:key2,value:value2} ]}
    这样不香吗?
    yiqunz
        14
    yiqunz  
       2020-02-16 10:43:49 +08:00
    t/629474
    关于 json 风格的讨论 请查阅
    luckylo
        15
    luckylo  
       2020-02-16 10:50:29 +08:00 via Android
    归根结底。还是数据结构设计问题
    binux
        16
    binux  
       2020-02-16 10:52:49 +08:00 via Android
    归根结底。还是菜
    mcfog
        17
    mcfog  
       2020-02-16 11:50:06 +08:00 via Android
    这事情对 js 确实不难,可是楼主你自己好好想想,key1 key2 是动态的你怎么个用解构拿里面的值
    sagaxu
        18
    sagaxu  
       2020-02-16 12:02:18 +08:00 via Android
    不难,但是脏啊,这样的接口得捏着鼻子调用
    abcbuzhiming
        19
    abcbuzhiming  
       2020-02-16 12:32:44 +08:00
    key 都不固定的? key 不固定我怎么知道你那个键代表啥意思?怎么会出现 key 都不固定的设计?
    这是哪个设计的,键盘砸它脸上去
    charlieputon
        20
    charlieputon  
       2020-02-16 12:36:14 +08:00 via Android
    心疼你们安卓,遇到你这样写接口的真是倒了霉了。
    clf
        21
    clf  
       2020-02-16 12:55:05 +08:00
    可以做到,且很容易的,做不到就是真的菜。

    使用 jackson 或者 fastjson 将 { key1: value1, key2: value2 } 转换为 Map。

    Map.keySet()能获得所有的 key 值,Map.entrySet()获取所有的<K, V>键值对。
    serge001
        22
    serge001  
    OP
       2020-02-16 13:00:39 +08:00 via Android
    @mcfog 不好意思 这里表达的不是很准确 跟解构确实没关系 我这样是因为上报的对象里面有其他固定字段 所以直接解构这个 extra 对象合并另外几个固定字段
    serge001
        23
    serge001  
    OP
       2020-02-16 13:04:12 +08:00 via Android
    @yiqunz 确实是接口设计的不够合理 不改接口原因是这个接口已经存在比较久了 前端别的地方已经接入
    wwwjf
        24
    wwwjf  
       2020-02-16 13:23:08 +08:00 via Android
    有一说一,在 Android 上处理这种接口数据确实比较蛋疼,最近半年都在处理这种数据,也是多端都使用了很久的接口
    clf
        25
    clf  
       2020-02-16 13:25:10 +08:00
    @serge001
    其实我觉得这样的数据结构设计没啥问题。jsonObject 本来就是一个特殊的键值对的 list。
    获取指定 key 的键值对是最快的,每个语言都提供了遍历键值对的方式,只不过你们的安卓开发不会而已。

    @jinhan13789991
    你这样设计有一个很明显的问题,假设数据里一共有 n 个键值对,我获得某个键值对的时间复杂度是 O(n),而使用楼主的存储方式哈希映射下时间复杂度是 O(1)。
    anxiousPumpkin
        26
    anxiousPumpkin  
       2020-02-16 13:36:32 +08:00
    public Map<String, Object> extra;

    这样就好啦,然后遍历 map 即可获取 key1、key2
    rosu
        27
    rosu  
       2020-02-16 13:37:49 +08:00
    有一说一,如果真如楼主内容说的:key 和 value 都是字符串,那么问题不大。无非用 Map<String, String> 接然后遍历上报。

    但是如果 value1 和 value2 里面是一个对象的话,那就比较蛋疼了;如果还要取对象里的值的话,那就更加蛋疼;如果 Android 这边用的是 Gson,那就非常蛋疼了。

    之前遇到,同一个 key,返回不同类型的 value。分别是 String 和 Object。处理起来贼麻烦。
    learningman
        28
    learningman  
       2020-02-16 13:39:06 +08:00 via Android
    key 本身就不应该带值。。。什么鬼设计
    wwwjf
        29
    wwwjf  
       2020-02-16 13:47:19 +08:00 via Android
    @lychs1998 虽然动态 key 数据时间复杂度是 O(1),但是接下来还要对数据做转换,转成对应的实体类对象,还是要循环 n 次,时间复杂度还是 O(n)
    clf
        30
    clf  
       2020-02-16 14:14:06 +08:00
    @wwwjf
    Map 转换成实体的时间复杂度和 Map 无关,和目标类型含有的字段数有关。

    假设 Map 里有 n 个键值对,目标类型里有 m 个属性。转换的时间复杂度是 O(m),逻辑是查询 m 次属性名对应的值。

    假设 List 里有 n 个键值对,目标类型有 m 个属性。转换的逻辑是提出每一个属性名,去 list 中遍历是否存在这样的 key 值,时间复杂度应该是 O(m*n)。
    clf
        31
    clf  
       2020-02-16 14:22:03 +08:00
    @rosu
    这样解析我用 fastjson 写过的,甚至还解析了 List 里套 List。可以参考我的开源项目的 CatContainer 对象的 put 方法的调用链: https://github.com/lychs1998/CatMock
    rosu
        32
    rosu  
       2020-02-16 14:55:59 +08:00 via iPhone
    @lychs1998 感谢回复。看了您的代码,实现方式就是遍历取值建立映射。我们之前也考虑过这样实现。唯一担心的还是耗时问题。如果直接把 json 丢进去转,正如您上面说的,时间复杂度会是 O(m*n )。如果 json 数据比较多(列表信息之类),可能会有潜在的性能问题。(只是有这个感性担忧,没有量化)。

    所以我们当时的做法是兼容接口,因为这样的接口是少数,所以采用手动解析的方式,只遍历和取值到业务需要的键值。

    不过您的代码对我也有很大启发,非常感谢~
    Aresxue
        33
    Aresxue  
       2020-02-16 16:11:39 +08:00
    不难
    tairan2006
        34
    tairan2006  
       2020-02-16 17:45:12 +08:00
    后端用 JsonNode 比较常见…如果不好处理就把 key 和 value 做成数组吧
    serge001
        35
    serge001  
    OP
       2020-02-16 20:53:43 +08:00
    @yiqunz 因为 key 跟 value 都是产品 /运营在后台配置的,是埋点的自定义数据, 确实接口设计成 key/value 的数组是比较合理的. 但是对于前端来说设计成对象写起来的确会方便很多
    zhaorunze
        36
    zhaorunze  
       2020-02-16 22:19:34 +08:00
    @serge001 你自己图方便了,还说后端强势
    serge001
        37
    serge001  
    OP
       2020-02-17 08:51:54 +08:00
    @zhaorunze 接口是后端定的啊....
    wysnylc
        38
    wysnylc  
       2020-03-14 17:10:34 +08:00
    json 四种类型 字符串 数字 对象 数组
    对应 java String BigDecimal Map Collection
    你不会不代表没有
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2492 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 05:45 PVG 13:45 LAX 22:45 JFK 01:45
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86