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

Java 动态解析对象很难吗?

  •  
  •   serge001 · 43 天前 · 3428 次点击
    这是一个创建于 43 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    不过您的代码对我也有很大启发,非常感谢~
    Aresxue
        33
    Aresxue   43 天前
    不难
    tairan2006
        34
    tairan2006   43 天前
    后端用 JsonNode 比较常见…如果不好处理就把 key 和 value 做成数组吧
    serge001
        35
    serge001   42 天前
    @yiqunz 因为 key 跟 value 都是产品 /运营在后台配置的,是埋点的自定义数据, 确实接口设计成 key/value 的数组是比较合理的. 但是对于前端来说设计成对象写起来的确会方便很多
    zhaorunze
        36
    zhaorunze   42 天前
    @serge001 你自己图方便了,还说后端强势
    serge001
        37
    serge001   42 天前
    @zhaorunze 接口是后端定的啊....
    wysnylc
        38
    wysnylc   16 天前
    json 四种类型 字符串 数字 对象 数组
    对应 java String BigDecimal Map Collection
    你不会不代表没有
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3448 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 10:37 · PVG 18:37 · LAX 03:37 · JFK 06:37
    ♥ Do have faith in what you're doing.