The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
dzdh

怎么优雅的处理不固定的 json 内容

  •  
  •   dzdh · Jul 3, 2023 · 5922 views
    This topic created in 1220 days ago, the information mentioned may be changed or developed.

    比如如下 json,怎么写 struct

    {
    "elements": [
        { "type":abc, "这个字段只在 type=abc 时出现":value},
        { "type":def, "这个字段只在 type=def 时出现":value},
        { "abc":"xx" ,"这个字段只在 abc=xx 时出现":"value"}
        ]
    }
    
    38 replies  •  2023-07-13 14:11:57 +08:00
    NessajCN
    NessajCN
    Jul 3, 2023
    1
    `json:"字段,omitempty"`
    seers
    seers
    Jul 3, 2023 via Android
    2
    放到 interface
    46fo
    46fo
    Jul 3, 2023
    3
    万能的 map[string]any
    jackbrother
    jackbrother
    Jul 3, 2023
    4
    后端设计不合理
    mineralsalt
    mineralsalt
    Jul 3, 2023
    5
    不要映射实体了,这种情况, 还不如直接用 JsonObject 取值来的方便
    bv
    bv
    Jul 3, 2023
    6
    @jackbrother 确实,这个 JSON 一点也不结构化,尤其是多出来的 `"abc":"xx"` 这一项显得数据关系更加松散。
    Seanfuck
    Seanfuck
    Jul 3, 2023
    7
    直接结构体字段写全去解析,没有的字段好像会给个默认值吧?
    yuan1028
    yuan1028
    Jul 3, 2023❤️1
    8
    struct 为了可读性,最好是把字段都写出来;
    牺牲可读性,为了代码的优雅的话,可以用字符串 json 处理库 https://github.com/tidwall/gjson ,这样不用解析。
    if-else 多,只能用设计模式优化。

    不过,在细微逻辑处,go 还是直来直去更合适,除非业务逻辑也比较明晰。
    exkernel
    exkernel
    Jul 3, 2023
    9
    gjson +1
    HelloAmadeus
    HelloAmadeus
    Jul 3, 2023❤️1
    10
    就是 oneof 的语法,oneof 也可以理解为 optional ,设计上无外乎两种方式,一种加 type 表示类型,和你这个例子类似,另外一种就是不加 type ,按优先级取值,按你这个例子就是设计上如果存在 "这个字段只在 type=abc 时出现" 对应的值,就不会取 "这个字段只在 type=def 时出现" 这个值了。
    这两种方式,无论怎么样,struct 都要把所有可能的结构都写上,都得写成
    ```
    type Element struct {
    Type string `json:"type"`
    TypeABCValue *struct {
    } `json:"这个字段只在 type=abc 时出现"`
    TypeDEFValue *struct {
    } `json:"这个字段只在 type=def 时出现"`

    ABC string `json:"type"`
    ABCXXValue struct {
    } `json:"这个字段只在 abc=xx 时出现"`
    ```
    ziyeziye
    ziyeziye
    Jul 3, 2023
    11
    gjson +1
    WaldenHorizon
    WaldenHorizon
    Jul 3, 2023
    12
    这种 key 都不同的还好处理,全声明就完了,赞同 10 楼
    wheeler
    wheeler
    Jul 3, 2023 via iPhone❤️1
    14
    rawMessage 根据 type 二次 unmarshal
    Trim21
    Trim21
    Jul 3, 2023 via Android
    15
    如果可能的 key 只有你提到的这 4 5 种的话,像 10 楼那样写个 struct 把所有可能的 key 都写上就好了…
    SimbaPeng
    SimbaPeng
    Jul 3, 2023
    16
    @wheeler 审题朋友,rawMessage 只适合 key 相同的情况,楼主这是 key 都不同
    byte404
    byte404
    Jul 3, 2023
    17
    gjson ? 取的时候判断一下
    ccde8259
    ccde8259
    Jul 3, 2023 via iPhone
    18
    有的 json 包 unmarshal 出来的是 ast.Node
    otakustay
    otakustay
    Jul 3, 2023
    19
    @jackbrother 也不能说不合理吧,从类型角度考虑这就是个 union type ,要说语言的类型能力不足也行
    a2231243
    a2231243
    Jul 3, 2023
    20
    structpb.Struct 这个挺好用
    rb6221
    rb6221
    Jul 3, 2023
    21
    这种内容,一般上游是 php ,要么就是这个项目的老架构是用 php 后面改 go 重写的
    mxT52CRuqR6o5
    mxT52CRuqR6o5
    Jul 3, 2023
    22
    abc 这个 key 是动态的?
    dzdh
    dzdh
    OP
    Jul 3, 2023
    23
    @mxT52CRuqR6o5 其他也是动态的。后端是 php 类似 class TypeA impl jsonserialize { tojson: return [type:...
    Justin13
    Justin13
    Jul 3, 2023 via Android
    24
    上 jsonschema
    lisxour
    lisxour
    Jul 3, 2023
    25
    这种就不应该上结构体了,用 gjson 之类的去取
    CloveAndCurrant
    CloveAndCurrant
    Jul 3, 2023
    26
    推荐 fastjson: github.com/valyala/fastjson
    和 fasthttp 一个作者开发的
    shawn4me
    shawn4me
    Jul 3, 2023
    27
    我之前做需求开发的时候也遇到这种动态字段的问题。我通常的做法是:类型作为一个字段,跟着类型变动的其他字段使用 json 字段统一存在一个字段里面。形成一个两级关系,这样就可以放心根据 type 字段进行取用了。Go 用内嵌应该也能做到,再加一个 omitempty 就能避免无用字段出现了。
    bunny189
    bunny189
    Jul 3, 2023
    28
    我个人评价为你们后端有病
    lisongeee
    lisongeee
    Jul 3, 2023
    29
    如果是 typescript/scala 的话,就是一个很简单的 联合类型
    sadfQED2
    sadfQED2
    Jul 3, 2023 via Android
    30
    直接上正则吧,别解析了
    huzhizhao
    huzhizhao
    Jul 3, 2023 via iPhone❤️1
    31
    不知道什么类型的业务会不抽象🤔
    alexapollo
    alexapollo
    Jul 4, 2023
    32
    条件结构的需求非常常见。比如不同返回码对应了不同的输出 —— 在上古 C 语言时期就已经有大量对应设计。

    如: http://c.biancheng.net/view/2035.html 中有 C 语言的 union 例子

    在 Python 中,你可以使用支持 Union 类型的库来实现这个功能,比如 pydantic: https://docs.pydantic.dev/latest/usage/types/unions/

    在其他语言中,你也应该搜索:<lang> json union ,来找到一个恰当的实现
    Leviathann
    Leviathann
    Jul 4, 2023
    33
    数组里后面的元素依赖前面的元素的 type 字段?
    什么勾把接口
    cheng6563
    cheng6563
    Jul 4, 2023
    34
    @huzhizhao PHP 后台能给你个 JSON 已经很不错了
    rs9G7IrdOdiNR3h1
    rs9G7IrdOdiNR3h1
    Jul 4, 2023
    35
    使用 com.google.gson.JsonDeserializer
    troywinter
    troywinter
    Jul 4, 2023
    36
    明显结构设计不合理
    huzhizhao
    huzhizhao
    Jul 5, 2023 via iPhone
    37
    @cheng6563 确实,深有体会
    awanganddong
    awanganddong
    Jul 13, 2023
    38
    这个帖子是一个解决方案
    Go 如何解析 json 内部结构不确定的情况

    https://my.oschina.net/u/4628563/blog/4724059
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3295 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 84ms · UTC 04:24 · PVG 12:24 · LAX 20:24 · JFK 23:24
    ♥ Do have faith in what you're doing.