提问一个用 Java 解析 JSON 的方法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
thebeacon
V2EX    Java

提问一个用 Java 解析 JSON 的方法

  •  
  •   thebeacon 2023-08-10 13:58:23 +08:00 2613 次点击
    这是一个创建于 801 天前的主题,其中的信息可能已经有所发展或是发生改变。

    业务需要按照”response. customerInfo.children“来获取到每个 children 节点 list 并需要包含该节点的所有父节点及其属性(理论上好像只要在解析的时候将父节点传进来即可,因为子节点确定了那他的父节点肯定也是确定的,不存在 list 的问题),想了半天没有想出来,请各位大佬支支招!

    原 json:

    { "response": { "customerInfo": [ { "uuid": "59a49249342f4262bd59ea2e36ac40d3", "name": "张三", "phoneNo": "15566669999", "idCard": "123456789965412544545", "wife": { "uuid": "51e211b7d1e54578b0093a5418868aa6", "name": "李四", "phoneNo": "15566668888", "idCard": "1236547896513245" }, "children": [ { "uuid": "8e1b40a3bc4a4f709a7076002132c7e3", "name": "张五", "phoneNo": "15523645896", "idCard": "523641528965425" }, { "uuid": "cd73bd47b6a945e0b3ca86927a154c1b", "name": "张六", "phoneNo": "15562458952", "idCard": "652154258962541" } ] }, { "uuid": "c752f9ff5a0d4776880e8ea1f0fcc482", "name": "王五", "phoneNo": "13652366548", "idCard": "123654856525665" } ] } } 

    解析后需要得到的 list

    [ { "response": { "customerInfo": { "uuid": "59a49249342f4262bd59ea2e36ac40d3", "name": "张三", "phoneNo": "15566669999", "idCard": "123456789965412544545", "wife": { "uuid": "51e211b7d1e54578b0093a5418868aa6", "name": "李四", "phoneNo": "15566668888", "idCard": "1236547896513245" }, "children": { "uuid": "8e1b40a3bc4a4f709a7076002132c7e3", "name": "张五", "phoneNo": "15523645896", "idCard": "523641528965425" } } } }, { "response": { "customerInfo": { "uuid": "59a49249342f4262bd59ea2e36ac40d3", "name": "张三", "phoneNo": "15566669999", "idCard": "123456789965412544545", "wife": { "uuid": "51e211b7d1e54578b0093a5418868aa6", "name": "李四", "phoneNo": "15566668888", "idCard": "1236547896513245" }, "children": { "uuid": "cd73bd47b6a945e0b3ca86927a154c1b", "name": "张六", "phoneNo": "15562458952", "idCard": "652154258962541" } } } } ] 

    就相当于是把每个子节点单独拿出来和他的各级父节点组成一个 JsonObject ,大佬们有没有什么妙招哇

    19 条回复    2023-08-11 12:52:34 +08:00
    blankmiss
        1
    blankmiss  
       2023-08-10 14:04:34 +08:00
    转成对象然后操作
    thebeacon
        2
    thebeacon  
    OP
       2023-08-10 14:06:41 +08:00
    @blankmiss 如果是固定格式的可以这样做,关键就是这个 json 是不固定的,需要通用化编码
    lyxeno
        3
    lyxeno  
       2023-08-10 14:08:57 +08:00
    你就正常创建一个 CustomerInfo 实体类拿 jackson 去反序列化生成出实体类后,
    再根据你需要得到的形态去构建对象,然后 jackson 序列化为 json 就好了

    ```java
    @Data
    class CustomerInfo{
    String uuid;
    String name;
    /* 其他属性 */
    List<CustomerInfo> children;
    CustomerInfo wife;
    }
    ```
    lyxeno
        4
    lyxeno  
       2023-08-10 14:10:03 +08:00
    实在不行反序列化成 Map 去做处理也可以的。就是丑陋了点
    darkengine
        5
    darkengine  
       2023-08-10 14:12:17 +08:00
    格式不固定也得有规律吧,用个 type 之类的参数代表不行么
    thebeacon
        6
    thebeacon  
    OP
       2023-08-10 14:34:53 +08:00
    @darkengine 产品就是要整一个无敌通用,什么 json 进来我们都要根据一个 key 来拆分出多个子节点列表(包含所有唯一父节点内容)
    thebeacon
        7
    thebeacon  
    OP
       2023-08-10 14:35:24 +08:00
    @lyxeno #4 感谢回复,实际上这个 json 不是特定格式的,没办法硬编码
    YepTen
        8
    YepTen  
       2023-08-10 14:52:16 +08:00
    用 JSON 的 tree model 试试
    thinkershare
        9
    thinkershare  
       2023-08-10 15:09:12 +08:00
    @thebeacon 各个 json 库不是都有自己的未解析的 Json Object 吗?按照 JSON 可能的格式逐个扫描吧。再不行你自己写个 json 序列&反序列化器好了,反正也不是什么难事,这样性能反正也不会好到哪里去,所以完全不需要考虑 JSON 库的性能优化。
    6IbA2bj5ip3tK49j
        10
    6IbA2bj5ip3tK49j  
       2023-08-10 15:25:11 +08:00
    循环 jsonnode 的节点,然后根据是不是 array 做判断处理,递归下去即可。
    你需要确定你的规则。
    比如,父节点的兄弟节点也是数组,期望得到什么样的结果?

    {
    "keyA": [
    {
    "name": "M"
    },
    {
    "name": "N"
    }
    ],
    "keyB": [
    {
    "name": "O"
    },
    {
    "name": "P"
    }
    ]
    }
    gogo789
        11
    gogo789  
       2023-08-10 15:59:01 +08:00
    这个 json 有点混乱了。首先会有一个 customerInfoDTO.java 里面包含 uuid,name,phoneNo...字段和 wife.java,children.java 两个对象。你直接通过 JSONObject.parseObject(jsonStr,customerInfoDTO.class) 除了 children 都可以解析到,关于 children 就只能自己手动处理了。可以通过 jsonObject.getJSONObject("response").getJSONArray("customerInfo").getJSONObject(0).getJSONArray("children") 获取到一个 children 的 jsonArray ,然后手动遍历解析这个 Array ,复制上面的解析结果往里面填充 children
    Dlin
        12
    Dlin  
       2023-08-10 16:04:33 +08:00
    可以先转为 ObjectNode,再根据属性来重新构建新的 ObjectNode
    xinxingi
        13
    xinxingi  
       2023-08-10 16:45:49 +08:00
    @thebeacon 考虑到你的 json 格式不固定,那就简单粗暴一点。拿到原 json 后,把原 json 的 response. customerInfo.children 全部拿出来装入集合。清空原 json 中的 response. customerInfo.children.拿刚才的集合一个一个的全部遍历填充进去。结束
    bill110100
        14
    bill110100  
       2023-08-10 17:01:12 +08:00
    @thebeacon 那你只能和产品怼,要不改需求,要不给开放时间,或者干脆要求换语言框架,理由很明确,java 强类型语言,不可能做到灵活多变的参数系统,
    还有,如果数据类型可以有某些特殊的字段,或者可以给你传输一些可以辨别格式的字段的话,可以通过多态的形式来转换,jackson 有做多态转换的注解,根据传输的参数是否有某字段为判断条件,将 json 反序列化为某一个父类下的不同子类。
    @JsonTypeInfo @JsonSubTypes 这几个注解可以看一下。
    JinTianYi456
        15
    JinTianYi456  
       2023-08-10 17:37:58 +08:00
    JSON.parseObject("")
    .getJSONObject("response")
    .getJSONArray("customerInfo")
    .stream()
    .map(t -> Collections.singletonMap("response", Collections.singletonMap("customerInfo", t)))
    .collect(Collectors.toList());

    这样?
    Corolin
        16
    Corolin  
       2023-08-10 17:39:41 +08:00
    好像 JsonPath 可以 反过来一层层去取?$.response.customerInfo[*]
    https://jsonpath.com/
    c3de3f21
        17
    c3de3f21  
       2023-08-10 18:13:10 +08:00
    得需要个 type 字段。。。
    c3de3f21
        18
    c3de3f21  
       2023-08-10 18:13:34 +08:00
    或者说需要一些 描述 json 本身的字段才行。
    mmdsun
        19
    mmdsun  
       2023-08-11 12:52:34 +08:00 via iPhone
    转对象处理,动态的用在对象里面用 map 声明 @JsonAnyGetter 、 @JsonAnySetter 即可。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2669 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 09:17 PVG 17:17 LAX 02:17 JFK 05:17
    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