Java 动态解析对象很难吗?

2020-02-16 09:00:12 +08:00
 serge001

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

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

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

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

6082 次点击
所在节点    Java
38 条回复
clf
2020-02-16 12:55:05 +08:00
可以做到,且很容易的,做不到就是真的菜。

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

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

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

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

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

之前遇到,同一个 key,返回不同类型的 value。分别是 String 和 Object。处理起来贼麻烦。
learningman
2020-02-16 13:39:06 +08:00
key 本身就不应该带值。。。什么鬼设计
wwwjf
2020-02-16 13:47:19 +08:00
@lychs1998 虽然动态 key 数据时间复杂度是 O(1),但是接下来还要对数据做转换,转成对应的实体类对象,还是要循环 n 次,时间复杂度还是 O(n)
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
2020-02-16 14:22:03 +08:00
@rosu
这样解析我用 fastjson 写过的,甚至还解析了 List 里套 List。可以参考我的开源项目的 CatContainer 对象的 put 方法的调用链: https://github.com/lychs1998/CatMock
rosu
2020-02-16 14:55:59 +08:00
@lychs1998 感谢回复。看了您的代码,实现方式就是遍历取值建立映射。我们之前也考虑过这样实现。唯一担心的还是耗时问题。如果直接把 json 丢进去转,正如您上面说的,时间复杂度会是 O(m*n )。如果 json 数据比较多(列表信息之类),可能会有潜在的性能问题。(只是有这个感性担忧,没有量化)。

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

不过您的代码对我也有很大启发,非常感谢~
Aresxue
2020-02-16 16:11:39 +08:00
不难
tairan2006
2020-02-16 17:45:12 +08:00
后端用 JsonNode 比较常见…如果不好处理就把 key 和 value 做成数组吧
serge001
2020-02-16 20:53:43 +08:00
@yiqunz 因为 key 跟 value 都是产品 /运营在后台配置的,是埋点的自定义数据, 确实接口设计成 key/value 的数组是比较合理的. 但是对于前端来说设计成对象写起来的确会方便很多
zhaorunze
2020-02-16 22:19:34 +08:00
@serge001 你自己图方便了,还说后端强势
serge001
2020-02-17 08:51:54 +08:00
@zhaorunze 接口是后端定的啊....
wysnylc
2020-03-14 17:10:34 +08:00
json 四种类型 字符串 数字 对象 数组
对应 java String BigDecimal Map Collection
你不会不代表没有

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/644933

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX