Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ORM and http Request deserialization should not rely on gconv.Struct #4099

Open
cyjaysong opened this issue Jan 6, 2025 · 4 comments
Open
Labels

Comments

@cyjaysong
Copy link
Contributor

cyjaysong commented Jan 6, 2025

Is your feature request related to a problem?

Option Yes

Describe the solution you'd like

目前 Orm和 http Request反序列化 均使用 gconv.Struct 反序列化。但两者在场景的反序列化逻辑上存在冲突。
Orm 查询返回的结果反序列化到对象场景中,数据库的 json字段数据应当严格按照Json协议反序列化到对象中的对应字段

type User struct {
   Id int64 `orm:id`
   Name   string `orm:name`
   Other  UserOther ` orm:other` // 对应数据库中的json数据类型
}

type UserOther struct {
         ...
}

数据中的other 为Json数据,应按照Json的反序列化方式反序列化到UserOther 对象

http Request反序列化反序列化的场景中,情况比较复杂,由于query和formData 允许一键多值,那么实际query和formData 的整体数据结构是map[string][]string。 但是接收参数的对象结构可能存在两种情况

type Req1 struct {
    Keys []string   `p:keys`
}
type Req2 struct {
    Key string  `p:key`
} 

反序列化到Req1中时,query或formData中keys参数无论传递了多少个值,都会被放到[]string中;反序列化到Req2中时若key传递了一个值,那么Key就等于key参数的值,若key 传递多个值,只会把多个key值的最后一个值赋值到Key

gconv的定位应当是方便开发数据类型转换的工具。目前gconv为了兼容http Request反序列化场景以及解决#3465 这种问题,用gconv.Struct转换时,会把某个字段值为塞入切片中。看似解决了http Req1 场景,但这也使得,在orm的JSON解析场景时,如果数据库的某json字段值为null,然后该字段的在结构体中字段对于的数据类型为[]string, 反序列化回来的值为["null"],预期结果不符,详见#4086

Describe alternatives you've considered

orm 反序列化方案可以产考 https://gitea.com/xorm/xorm
http Request 反序列化方案可以产考 https://github.com/gorilla/schema

Additional

xorm 也支持我在 #4086 中提到的需求

@Issues-translate-bot Issues-translate-bot changed the title ORM 和 http Request反序列化不应依赖 gconv.Struct ORM and http Request deserialization should not rely on gconv.Struct Jan 6, 2025
@ninjashixuan
Copy link
Contributor

ninjashixuan commented Jan 7, 2025

一直觉得 http Request json 反序列化 不区分大小写和下划线,有点不严谨,一般文档约定前后端都遵守一种风格。

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


I have always felt that http Request json deserialization does not distinguish between uppercase and underscores, which is a bit lax.

@wln32
Copy link
Member

wln32 commented Jan 7, 2025

@cyjaysong 是否有可能将 https://github.com/gorilla/schema 这个库迁移到gf上?目前gf在解析http请求参数时,会做多次转换,做了许多无用功,例如

// 如果前端传递一个这样的json数据
{
  "name": "string",
  "jsonRaw": [
    {
        "jkey": "value1",
        "jkey2": 2
    },
    {
        "jkey": "value12",
        "jkey2": 22
    }
  ]
}
// 后端对应的接收结构体
type S struct{
    Name string `json:"name"`
    JsonRaw json.RawMessage `json:"jsonRaw"`
}

以上形式的参数,jsonRaw的value是个json数组,目前gf(内部调用标准的json)会解析为一个[]map,
即 ,然后再把这个[]map转成结构体S的JsonRaw 字段,从字符串到[]map,然后再从[]map到字符串。看起来这种转换是无意义的

@wln32
Copy link
Member

wln32 commented Jan 7, 2025

@cyjaysong @gqcn 对于http和orm的序列化,我也认同 @cyjaysong 说的,gconv应该只做go类型之间的转换,不应该参与到json,xml,yaml等等这种特定格式的转换上,
json的类型只有number,string,bool,array,object,null,比起go的类型(int,int8,bool,string,time,otherStruct,...)比起来还算是简单的,
orm比起json就跟简单了,目前go的第三方数据库驱动,也会把数据库的类型映射为int,int64,float64,string,time,[]byte,这几种类型,可以覆盖95%以上的场景,而且orm的类型比起go和json的类型,没有复合类型,就像go的struct或者map,json的object,array这种
完全可以针对http和orm的场景定制一些独立于gconv.Struct,gconv.Scan之外的转换逻辑,当然,基础类型的转换是可以复用的,

@gogf gogf deleted a comment from Issues-translate-bot Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants