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

Java 动态解析对象很难吗?

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

    接口返回的是 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
    https://www.v2ex.com/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   ·   实用小工具   ·   5534 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 06:04 · PVG 14:04 · LAX 22:04 · JFK 01:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.