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

JSON 数据中,要将 value 转成特定的值,如何优雅的转换

  •  
  •   Ranni · 2023-01-06 00:31:00 +08:00 · 3452 次点击
    这是一个创建于 470 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如有个这样的 response

    {
        "examinationStatus":{
            "absent":false,
            "noAbsent":true
        },
        "grades":{
            "math":90
        }
    }
    

    然后我要返回的数据类型是这样的

    {
        "isAbsent":false,
        "grades":{
            "math":"优秀"
        }
    }
    

    现在小组里的代码是将第一个 Json String 转成 map ,然后一堆 if 判断,将值塞到一个对象里去,一百多行了,看起来真的难受,想请教下有没有没有比较好的优化方案

    26 条回复    2023-01-09 12:08:51 +08:00
    IvanLi127
        1
    IvanLi127  
       2023-01-06 00:47:17 +08:00 via Android
    你啥语言,我用 js 写的话没几行。。就直接写,你不会是 java 吧
    autoxbc
        2
    autoxbc  
       2023-01-06 01:15:27 +08:00   ❤️ 12
    Java 开发者:虽然不知道为什么,我先在这里放上一个 class ;
    JS 开发者:虽然忘了怎么写的,不过已经写完了,反正没报错;
    hhjswf
        3
    hhjswf  
       2023-01-06 02:03:27 +08:00 via Android   ❤️ 2
    既然前端那么好处理,那就交给前端做。。。
    TWorldIsNButThis
        4
    TWorldIsNButThis  
       2023-01-06 02:17:56 +08:00 via iPhone
    如果字段是固定的 java 的话就建两个 class 呗
    ddvswgg
        5
    ddvswgg  
       2023-01-06 04:57:52 +08:00
    def conversion(input_data):
    dict_grades = {
    "isAbsent":None,
    "grades":{}
    }

    # attendance
    if input_data['examinationStatus']['absent']:
    dict_grades['isAbsent'] = True
    else:
    dict_grades['isAbsent'] = False

    # grades
    for subject, score in input_data['grades'].items():
    if score >= 90:
    dict_grades['grades'][subject] = '优秀'
    else:
    dict_grades['grades'][subject] = '垃圾'

    return dict_grades


    -------------------------
    input_data = {
    "examinationStatus":{
    "absent":False,
    "noAbsent":True
    },
    "grades":{
    "math":90,
    'english':50
    }
    }


    output_data = {'isAbsent': False, 'grades': {'math': '优秀', 'english': '垃圾'}}



    这是你想要的么?
    Edward4074
        6
    Edward4074  
       2023-01-06 05:09:29 +08:00 via iPhone
    JsonPath ?
    zxCoder
        7
    zxCoder  
       2023-01-06 09:15:34 +08:00
    看这描述好像是 Java 。。。
    ljsh093
        8
    ljsh093  
       2023-01-06 09:21:07 +08:00
    jsonpath 判断值,class 类转换,map 火葬场
    oneisall8955
        9
    oneisall8955  
       2023-01-06 10:00:06 +08:00 via Android
    写一个工具,也不用多少时间吧,有时间写个 Demo 。先说个思路,有个抽象的规则处理类,存取目标 jsonpath 和要删除 jsonpath ,还有替换成的 jsonpath 和对应的 value 等等。然后写各个实现,用个 list 存取各个规则实现的实例,遍历处理
    bk201
        10
    bk201  
       2023-01-06 10:16:03 +08:00
    map 做值映射,然后遍历替换?
    zhy0216
        11
    zhy0216  
       2023-01-06 11:46:28 +08:00   ❤️ 2
    xiangyuecn
        12
    xiangyuecn  
       2023-01-06 12:01:26 +08:00
    写两个函数的事,get 、set

    什么 class 不 class 的,map 一把梭,两行代码搞定
    ragnaroks
        13
    ragnaroks  
       2023-01-06 12:44:03 +08:00
    如果 "90" => "优秀" 是固定的,那么直接做字符串替换就行了?
    dreampuf
        14
    dreampuf  
       2023-01-06 14:12:37 +08:00
    jq?
    ```
    def grade(score): if score >= 90 then "优秀" else "不合格" end; {isAbsent: .examinationStatus.absent, grades: { math: grade(.grades.math) }}
    ```
    chenjiangui998
        15
    chenjiangui998  
       2023-01-06 14:28:29 +08:00
    for (let i=80;i<=100;i++) {
    let reg = `${i}`
    json = json.replaceAll(reg, '优秀')
    }
    直接正则替换? 伪代码
    issakchill
        16
    issakchill  
       2023-01-06 17:43:55 +08:00
    JsonPath
    NGXDLK
        17
    NGXDLK  
       2023-01-06 17:52:51 +08:00
    这完全是两种不同的结构,加两个类吧
    zhazi
        18
    zhazi  
       2023-01-06 18:32:16 +08:00
    如果你要动态转换可以参考这个方案: https://docs.oracle.com/cd/E29542_01/doc.1111/e26693/dc_intro.htm#WCCAA2894
    如果你想的是静态转换直接使用 MapStruct
    @Mapping(source="source.examinationStatus.absent",target="isAbsent")
    Target convert(Source souce)
    Ranni
        19
    Ranni  
    OP
       2023-01-06 23:41:13 +08:00
    不好意思,忘记说了是 Java
    Ranni
        20
    Ranni  
    OP
       2023-01-06 23:41:34 +08:00
    @zhazi 谢谢,我看看这两方案
    Ranni
        21
    Ranni  
    OP
       2023-01-06 23:45:04 +08:00
    @ddvswgg 谢谢大佬这么详细的回复,这种 hard code 是一种方案,但是我自己想要的是,在业务方法里尽可能少的代码,想用某种设计模式,把这些处理塞到某个 vo 类,暂时想到的是用建造者模式,将转换的逻辑塞到 build 里
    Nnq
        22
    Nnq  
       2023-01-08 07:28:48 +08:00
    "isAbsent":false 你是认真的么? 好像阿里的最佳实践里也提到不要这么写吧
    forward
        23
    forward  
       2023-01-08 12:14:13 +08:00
    这种事就交给前端吧,后端返回 “优秀” 这个中文不太好的,我写过一个 npm 包,很优雅~~
    硬要在后端转,估计也有类似的包,没有就自己写一个
    https://www.npmjs.com/package/class-converter

    import { property, typed, deserialize, toClass, toPlain } from 'class-convert';

    class GradesModel {
    @deserialize(val => (val >= 90 ? '优秀' : '普通'))
    @property()
    math: string;
    }

    class JsonResponse {
    @deserialize(val => val.absent)
    @property('examinationStatus')
    isAbsent: boolean;

    @typed(GradesModel)
    @property()
    grades: GradesModel;
    }

    const model = toClass(
    {
    examinationStatus: {
    absent: false,
    noAbsent: true,
    },
    grades: {
    math: 90,
    },
    },
    JsonResponse,
    );

    // {"isAbsent":false,"grades":{"math":"优秀"}}
    console.log(model);
    lmshl
        24
    lmshl  
       2023-01-08 15:38:40 +08:00
    😏
    Vaspike
        25
    Vaspike  
       2023-01-09 11:10:01 +08:00
    @lmshl #24 Kotlin yyds
    lmshl
        26
    lmshl  
       2023-01-09 12:08:51 +08:00
    @Vaspike kotlin 版随手写的,其实不安全,没有错误处理。按照生产级代码规范,应该多加 5 行的 data class 定义,做严格 ser/deser 。
    同样的逻辑用 Scala 写会安全很多,Option/Either 签名的方法都是默认实现了,flatMap/getOrElse 过去就好。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2953 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 08:32 · PVG 16:32 · LAX 01:32 · JFK 04:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.