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

golang 如何正确解析 Java 中 jackson 序列化的 json 数据?

  •  
  •   ZeroDu · 7 小时 7 分钟前 · 796 次点击
    [
        "com.test.UserInfo",
        {
            "userName": "`13123",
            "email": "",
            "roleIds": [
                "java.util.ArrayList",
                [
                    "109"
                ]
            ]
        }
    ]
    

    如上,因为 jackson 在序列化时写入了类型信息,所以在 golang 中如何正确解析数据(忽略其中的类型信息)?

    第 1 条附言  ·  4 小时 57 分钟前
    这就是 json 格式,上游配置没考虑兼容性,应该把类型信息放到单独字段里面。
    15 条回复    2025-01-22 19:00:33 +08:00
    jov1
        1
    jov1  
       6 小时 56 分钟前
    这个数据看起来更像是对序列化后的对象做了 toString()操作返回的字符串,肯定不是标准的 json ,即便带有类信息比如存到 redis ,使用 jackson 序列化完也应该是这样的结构,不会出现 "java.util.ArrayList"这种的
    {
    "@type": "com.xxx.xxx.XXX",
    "ids": [
    111,22
    ],
    "name": "你好"
    }
    guyeu
        2
    guyeu  
       6 小时 56 分钟前
    最好让上游改一下序列化方式,把类型信息当作字段放进 json ,如

    ```json
    {
    "@type": "com.test.UserInfo",
    "userName": "`13123",
    "email": "",
    "roleIds": [
    "java.util.ArrayList",
    [
    "109"
    ]
    ]
    }
    ```

    这样你只需要简单配置下自己这边的反序列化器忽略`@type`字段(很多时候也不需要配置,json 库默认忽略不认识的字段)。
    guyeu
        3
    guyeu  
       6 小时 53 分钟前
    我说的这个修改需要上游改一下这个类上`@JsonTypeInfo`注解的属性,或者修改下自己的`ObjectMapper`。
    guyeu
        4
    guyeu  
       6 小时 51 分钟前
    u1s1 ,Jackson 把多态对象的类型信息当作数组的元素序列化的方式略微少见,正经的 API 还是尽可能避免使用多态数据,或者专门定义一个描述类型信息的枚举,然后根据这个枚举来序列化/反序列化,使用 Jackson 也可以较简单地实现这样的机制。
    zhuisui
        5
    zhuisui  
       6 小时 28 分钟前
    ```
    // nodejs Buffer
    > Buffer.from([1]).toJSON()
    { type: 'Buffer', data: [ 1 ] }
    ```
    特定类型的对象 json 序列化结果本来就依赖于类型,默认行为只会考虑本平台的反序列化。
    要想跨平台识别,必须自定义序列化结果。
    json 本身只是信息携带标准格式,没什么非法不非法一说。
    body007
        6
    body007  
       6 小时 13 分钟前
    我这边是用 github.com/json-iterator/go 这个库的 jsoniter.Get 方法,示例如下,我是默认 "com.test.UserInfo" 和 "java.util.ArrayList" 这类数据都在第 0 项里面,所以用 data.Get(1) 取第 1 项。

    ```go
    package main

    import (
    "fmt"

    jsoniter "github.com/json-iterator/go"
    )

    func main() {
    s := `
    [
    "com.test.UserInfo",
    {
    "userName": "13123",
    "email": "[email protected]",
    "roleIds": [
    "java.util.ArrayList",
    [
    "109","209","309"
    ]
    ]
    }
    ]`
    data := jsoniter.Get([]byte(s), 1)
    var (
    userName = data.Get("userName").ToString()
    email = data.Get("email").ToString()

    roleIds []string
    )
    data.Get("roleIds", 1).ToVal(&roleIds)
    fmt.Printf("userName: %s, email: %s, roleIds: %#v\n", userName, email, roleIds)
    }
    ```
    fengjianche
        7
    fengjianche  
       6 小时 10 分钟前
    json 不是都一样的吗?怎么还跟语言有关系
    git00ll
        8
    git00ll  
       5 小时 59 分钟前
    让上游不要吧类型搞出来,这不是标准的 json
    Erroad
        9
    Erroad  
       5 小时 51 分钟前
    说明没做好序列化,变成了一堆 Object 或者说 interface 的数组
    afutureus
        10
    afutureus  
       5 小时 38 分钟前
    我盲猜是 redis 内的数据...
    000sitereg
        11
    000sitereg  
       5 小时 36 分钟前 via Android
    这个都不算 json 字符串,一眼看着像而已
    jhdxr
        12
    jhdxr  
       5 小时 33 分钟前
    @000sitereg @git00ll @jov1

    一堆说这不是 json/不是标准的 json 的。。。

    这 json 字符串哪不标准了?

    有规定说 json 里一个数组内的所有元素必须是同一个类型吗?虽然我也觉得这种用法很奇葩,但并不代表这种用法是非法的。
    siweipancc
        13
    siweipancc  
       5 小时 33 分钟前 via iPhone
    一眼 redis json ,设置 @type ,jackson 给前端就没问题了,gson 忽略未知 field 试试
    shyangs
        14
    shyangs  
       5 小时 30 分钟前
    通過了 JSON 驗證器, JSON 驗證器說是標準的 json.

    你若不能控制上游,則叫上游拿 API 文件出來, 看文件上是不是說這個 API 的 json 陣列第一個元素固定是類型.

    或者你能控制上游,直接改上游.
    ZeroDu
        15
    ZeroDu  
    OP
       4 小时 47 分钟前
    @body007 #6 这个适合单独的处理一些
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2493 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 15:48 · PVG 23:48 · LAX 07:48 · JFK 10:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.