V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
gam2046
V2EX  ›  Go 编程语言

如何解析动态类型的 json?

  •  
  •   gam2046 · 2022-11-11 15:42:38 +08:00 · 2897 次点击
    这是一个创建于 767 天前的主题,其中的信息可能已经有所发展或是发生改变。

    样例

    {
        "video": [
            1,
            2,
            3
        ],
        "video": {
            "a": {
                "aa": []
            }
        },
        "video_type": "template_a"
    }
    

    需求

    就像样例中那样,video 字段的类型有好几种,具体哪种是通过 video_type 字段决定。

    那么对于这种样子的 json ,使用 Golang 应该如何优雅的解析呢?

    (问为什么设计成样子的结构,以及解决方案是修改 json 的算了,人家已经定义好了,跑了好几年,不可能因为我改)

    18 条回复    2022-11-11 18:24:52 +08:00
    sardina
        1
    sardina  
       2022-11-11 16:13:42 +08:00 via iPhone
    先写一个结构体来解析对应的 video type 然后根据不同的 type 去用不同的结构体去解析 video 字段
    或者使用一个叫 gjson 的库试试
    lisongeee
        2
    lisongeee  
       2022-11-11 16:15:40 +08:00
    如果是 kotlin 可以用 密封类,如果是 typescript 可以用联合类型,如果是 go ,我不到啊
    iamzuoxinyu
        3
    iamzuoxinyu  
       2022-11-11 16:38:22 +08:00
    用 DOM 风格的 json 解析库。
    virusdefender
        4
    virusdefender  
       2022-11-11 16:40:32 +08:00
    先解析到只有一个字段 video_type 的 struct 上,然后判断类型后选择对应的 struct 再解析
    rrfeng
        5
    rrfeng  
       2022-11-11 16:41:27 +08:00
    如果每种 video 类型的格式固定,那就好办了

    把 video 字段定义为 json.RawMessage ,然后根据 type 再进一步 Unmarshal 即可。
    Ritter
        6
    Ritter  
       2022-11-11 16:42:25 +08:00
    把 video_type 对应的 struct 都枚举出来
    dzdh
        7
    dzdh  
       2022-11-11 16:48:23 +08:00
    go 的话,gjson 类似的库?

    if x.Get("XX").IsArray IsFloat / x.Get("XX").Array()[0].IsFloat/IsArray
    aw2350
        8
    aw2350  
       2022-11-11 16:52:45 +08:00
    gjson \ jsonparser
    Privileges
        9
    Privileges  
       2022-11-11 16:54:25 +08:00
    用 gjson 解析很方便
    Crawping
        10
    Crawping  
       2022-11-11 17:19:40 +08:00   ❤️ 1
    用 map[string]interface{} 根据 template 解析
    petercui
        11
    petercui  
       2022-11-11 17:21:57 +08:00
    Jackson 的话,继承 JsonDeserializer 然后自己一个字段一个字段的解析就行了。
    yulon
        12
    yulon  
       2022-11-11 17:22:15 +08:00
    Go 的 interface 和 map[string] 不是万能的?别的语言还要考虑塞个变体
    yeqown
        13
    yeqown  
       2022-11-11 17:26:52 +08:00
    #5 正解,文档里的 example 和你的场景完全一致 https://pkg.go.dev/encoding/json#example-RawMessage-Unmarshal
    Great233
        14
    Great233  
       2022-11-11 17:27:28 +08:00
    lisxour
        15
    lisxour  
       2022-11-11 17:41:11 +08:00
    我用的 github.com/bitly/go-simplejson ,然后使用 simplejson.NewJson(bytes)反序列化,接着用 GetXXX 、SetXXX
    lisxour
        16
    lisxour  
       2022-11-11 17:46:00 +08:00
    不需要定义任何结构体,可参考官方例子: https://github.com/bitly/go-simplejson/blob/master/simplejson_test.go
    sbex
        17
    sbex  
       2022-11-11 17:59:23 +08:00
    pkoukk
        18
    pkoukk  
       2022-11-11 18:24:52 +08:00
    先把 json decode 到 map[string]any
    然后 switch m[video_type]
    最后用 mapstructure 把 m[video] decode 到对应的 Struct
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5759 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 01:50 · PVG 09:50 · LAX 17:50 · JFK 20:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.