[
"com.test.UserInfo",
{
"userName": "`13123",
"email": "",
"roleIds": [
"java.util.ArrayList",
[
"109"
]
]
}
]
如上,因为 jackson 在序列化时写入了类型信息,所以在 golang 中如何正确解析数据(忽略其中的类型信息)?
1
jov1 8 天前
这个数据看起来更像是对序列化后的对象做了 toString()操作返回的字符串,肯定不是标准的 json ,即便带有类信息比如存到 redis ,使用 jackson 序列化完也应该是这样的结构,不会出现 "java.util.ArrayList"这种的
{ "@type": "com.xxx.xxx.XXX", "ids": [ 111,22 ], "name": "你好" } |
2
guyeu 8 天前
最好让上游改一下序列化方式,把类型信息当作字段放进 json ,如
```json { "@type": "com.test.UserInfo", "userName": "`13123", "email": "", "roleIds": [ "java.util.ArrayList", [ "109" ] ] } ``` 这样你只需要简单配置下自己这边的反序列化器忽略`@type`字段(很多时候也不需要配置,json 库默认忽略不认识的字段)。 |
3
guyeu 8 天前
我说的这个修改需要上游改一下这个类上`@JsonTypeInfo`注解的属性,或者修改下自己的`ObjectMapper`。
|
4
guyeu 8 天前
u1s1 ,Jackson 把多态对象的类型信息当作数组的元素序列化的方式略微少见,正经的 API 还是尽可能避免使用多态数据,或者专门定义一个描述类型信息的枚举,然后根据这个枚举来序列化/反序列化,使用 Jackson 也可以较简单地实现这样的机制。
|
5
zhuisui 8 天前
```
// nodejs Buffer > Buffer.from([1]).toJSON() { type: 'Buffer', data: [ 1 ] } ``` 特定类型的对象 json 序列化结果本来就依赖于类型,默认行为只会考虑本平台的反序列化。 要想跨平台识别,必须自定义序列化结果。 json 本身只是信息携带标准格式,没什么非法不非法一说。 |
6
body007 8 天前
我这边是用 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) } ``` |
7
fengjianche 8 天前
json 不是都一样的吗?怎么还跟语言有关系
|
8
git00ll 8 天前
让上游不要吧类型搞出来,这不是标准的 json
|
9
Erroad 8 天前
说明没做好序列化,变成了一堆 Object 或者说 interface 的数组
|
10
afutureus 8 天前
我盲猜是 redis 内的数据...
|
11
000sitereg 8 天前 via Android
这个都不算 json 字符串,一眼看着像而已
|
12
jhdxr 8 天前
@000sitereg @git00ll @jov1
一堆说这不是 json/不是标准的 json 的。。。 这 json 字符串哪不标准了? 有规定说 json 里一个数组内的所有元素必须是同一个类型吗?虽然我也觉得这种用法很奇葩,但并不代表这种用法是非法的。 |
13
siweipancc 8 天前 via iPhone
一眼 redis json ,设置 @type ,jackson 给前端就没问题了,gson 忽略未知 field 试试
|
14
shyangs 8 天前
通過了 JSON 驗證器, JSON 驗證器說是標準的 json.
你若不能控制上游,則叫上游拿 API 文件出來, 看文件上是不是說這個 API 的 json 陣列第一個元素固定是類型. 或者你能控制上游,直接改上游. |
16
kingcanfish 7 天前
@jhdxr JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array. An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence. https://www.json.org/json-en.html |
17
jhdxr 7 天前
@kingcanfish 没问题啊,OP 贴的这个哪儿不符合了?
|
18
a132811 7 天前
递归移除一下就可以了:
``` package main import ( "encoding/json" "fmt" ) func removeJavaTypes(input string) (string, error) { var data interface{} if err := json.Unmarshal([]byte(input), &data); err != nil { return "", fmt.Errorf("failed to unmarshal json: %w", err) } cleanedData, err := recursivelyRemoveTypes(data) if err != nil { return "", err } outputBytes, err := json.Marshal(cleanedData) if err != nil { return "", fmt.Errorf("failed to marshal json: %w", err) } return string(outputBytes), nil } func recursivelyRemoveTypes(data interface{}) (interface{}, error) { switch v := data.(type) { case []interface{}: if len(v) == 2 { _, isString := v[0].(string) if isString { return recursivelyRemoveTypes(v[1]) } } for i := range v { var err error v[i], err = recursivelyRemoveTypes(v[i]) if err != nil { return nil, err } } return v, nil case map[string]interface{}: for key := range v { var err error v[key], err = recursivelyRemoveTypes(v[key]) if err != nil { return nil, err } } return v, nil default: return data, nil } } func main() { input := ` [ "com.test.UserInfo", { "userName": "13123", "email": "[email protected]", "roleIds": [ "java.util.ArrayList", [ "109" ] ] } ] ` output, err := removeJavaTypes(input) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Output:", output) } } ``` |