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

被 go 语言的 json.Marshal 恶心到了

  •  
  •   qW7bo2FbzbC0 · 52 天前 · 10608 次点击
    这是一个创建于 52 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的需求是,输入 sql ,返回序列化后的 json 结果。

    在 python 中,官方库就可以返回[{'col1': 1, 'col2': '2', 'col3': true}....] 这种带类型的 json 结果。

    在 go 中如果已知 sql 返回的列数和列类型,也可以构造一个 struct 进行数据映射,然后用json.Marshal转为 json 。

    如果 sql 返回的列数和行类型未知,就很难受了,在 go/mysql 的官方 wiki 案例 中对于匿名的结果,使用了 interface 或者 sql.RawBytes ,但这两种替代方式在json.Marshal后都变成了 base64 encode 后的 string ,既丢失了类型也变异了结果( https://stackoverflow.com/questions/32501784/the-sqlx-library-gives-weird-base64-encoded-looking-results)

    请问各位在实际业务中遇到这个问题是怎么处理的?

    在其他语言中很自然的 object 序列化为原类型,在 go 的 json.Marshal 中怎么就全变成 string 了

    第 2 条附言  ·  45 天前
    130 条回复    2024-08-06 10:39:24 +08:00
    1  2  
    yrzs
        1
    yrzs  
       52 天前
    FrankFang128
        2
    FrankFang128  
       52 天前
    没遇到过,没看懂
    3img
        3
    3img  
       52 天前
    如果是不知道指针的类型,可以用反射啊
    dzdh
        4
    dzdh  
       52 天前   ❤️ 1
    我翻译一下。

    up 想要 go 实现 php 的 json_encode(PDO->fethcAll()) 不定义 struct
    NessajCN
        5
    NessajCN  
       52 天前
    首先 Marshal 是序列化,Unmarshal 是反序列化, 也就是从 byte 到 go struct 应该用 Unmarshal
    其次,对于未知的返回类型一般不 Unmarshal , 直接从 interface 里取键值,go 自带返回 ok 判断是否有这个 key
    譬如
    ```go
    type SqlResult map[string]interface{}
    var res SqlResult
    if col1,ok := res["col1"].(int32); ok {
    //...
    }
    ```
    povsister
        6
    povsister  
       52 天前
    你适合用 python
    sagaxu
        7
    sagaxu  
       52 天前
    根据 ColumnType 判断一下字段类型,自己写个转换,把[]byte 和[]uint8 都转成 string
    laikick
        8
    laikick  
       52 天前
    你适合用 PHP
    zxdstyle
        9
    zxdstyle  
       52 天前
    这不是 go 和 python 的区别,是强类型语言与弱类型语言的区别
    Goooooos
        10
    Goooooos  
       52 天前
    @zxdstyle 其实 python 也是强类型语言
    sagaxu
        11
    sagaxu  
       52 天前
    @laikick 除了 PHP ,Python 和 Java 也行,这件事情上,唯独 Go 比较大道至简
    james122333
        12
    james122333  
       52 天前 via Android
    你可以用 map[string]any 或 json.RawMessage
    james122333
        13
    james122333  
       52 天前 via Android
    map[string]any, []any...族繁不及备载
    Nazz
        14
    Nazz  
       52 天前
    要修改下结构体定义, 例如把 []uint8 换成 []uint16
    james122333
        15
    james122333  
       52 天前 via Android
    看 col 举例应该是[]map[string]any
    ChrisFreeMan
        16
    ChrisFreeMan  
       52 天前
    OP 赶紧跑吧你完了
    luhengyuorang
        17
    luhengyuorang  
       52 天前
    最开始用 py 或者 php 的来写 go ,很容易有代入感,经常看到别人把 go 写成 php
    dcalsky
        18
    dcalsky  
       52 天前   ❤️ 11
    收收 python 、js 、php 味。go 的正规业务里,都要得先定义 struct ,不到万不得已不用 map[string]any
    liaohongxing
        19
    liaohongxing  
       52 天前
    总结不适应强类型
    rekulas
        20
    rekulas  
       52 天前
    go 真冤 完全没看懂这跟 go 有什么关系
    qW7bo2FbzbC0
        21
    qW7bo2FbzbC0  
    OP
       52 天前
    @sagaxu 我去查了下 grafana 的代码,又查了下 sof ,对于未知返回类型的查询,的确是对各个类型自己去重新实现映射/序列化

    和 @NessajCN 说的差不多

    但是 java, c#这种都可以 getObject,然后直接对 Object 序列化出带类型的 json
    qW7bo2FbzbC0
        22
    qW7bo2FbzbC0  
    OP
       52 天前
    @sagaxu @NessajCN @james122333 但是 go 语言中,用 interface 或者 any 来模拟 java c#这种 getObject ,然后序列化,结果就是 base64 encode 后的 string
    cuiweiqiang
        23
    cuiweiqiang  
       52 天前
    既然用 sql 了,为啥还会存在“行类型未知”这种场景?
    james122333
        24
    james122333  
       52 天前 via Android
    是最好定义 struct 外加上泛型
    qW7bo2FbzbC0
        25
    qW7bo2FbzbC0  
    OP
       52 天前
    @dcalsky 肯定是有传入黑箱 sql ,返回 json 结果的场景,没遇到不等于没有。这和 python 、js 、php 味没关系,java c#都正常
    wildlife
        26
    wildlife  
       52 天前
    标准的 JSON 不是只能使用 "" 双引号包围的任意数量 Unicode 字符的集合吗?
    qW7bo2FbzbC0
        27
    qW7bo2FbzbC0  
    OP
       52 天前
    @cuiweiqiang 用 java 模拟 mysql 命令行工具,这个场景是不是 sql 已知,行类型未知?
    james122333
        28
    james122333  
       52 天前 via Android
    @qW7bo2FbzbC0

    你不能直接就一个 any 最起码知道它是字典阵列 不知道就先 json.RawMessage 根据内容 parse 一下用字典或阵列装
    xingjue
        29
    xingjue  
       52 天前
    你适合用 PHP 典型的脚本语言思想
    james122333
        30
    james122333  
       52 天前 via Android
    阿... Marshal 的话就直接 Marshal 成 json.RawMessage 就好了
    把字段定义成 json.RawMessage 即可
    MoYi123
        31
    MoYi123  
       52 天前   ❤️ 1
    @qW7bo2FbzbC0 怎么可能是 base64 后的 string 啊, 贴个例子看看. 八成是 unicode 吧, 提醒一下, json 必须是 utf8 编码的.
    qW7bo2FbzbC0
        32
    qW7bo2FbzbC0  
    OP
       52 天前
    在 go/sql 中,interface 或者 any 会返回[]byte ,在 json.Marshal 中,[]byte 会被序列化成 base64 encode 字符串


    `Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.`

    @NessajCN @sagaxu
    qW7bo2FbzbC0
        33
    qW7bo2FbzbC0  
    OP
       52 天前
    https://forum.golangbridge.org/t/json-encode-byte-array-as-hex-string-instead-of-base64/26751

    ```
    One must use reflection to walk and copy the original object replacing byte arrays with the user-defined type for which the MarshalJSON method is defined, but there’s probably no better way. An even uglier alternative is to post-process the JSON.
    ```
    fregie
        34
    fregie  
       52 天前
    犯懒就用 js python 就好了,何必选个强类型语言给自己找罪受呢
    Felldeadbird
        36
    Felldeadbird  
       52 天前
    用一门新语言时,最怕就是拿别的语言对比新学的语言。

    不想麻烦就定义结构体,一次定义全代码收益,要像脚本语言那么自然,就得多写一些代码转换。
    qW7bo2FbzbC0
        37
    qW7bo2FbzbC0  
    OP
       52 天前
    @fregie 1 、项目定型是这个语言。2 、类似的蹩脚问题不止这一个,在 go1.8 之前代码里面好多 inteface 飞来飞去,不仅丢失了类型还影响类型安全。 我讨厌 interface 转来转去也是犯懒,我觉得 go/sql 和 json.Marshal 对于匿名类型查询不友好也是犯懒?你扣帽子是什么态度?
    cs8425
        38
    cs8425  
       52 天前
    @qW7bo2FbzbC0 因为 json 的 string 必须为 UTF-8 而[]byte 不一定是 UTF-8
    Jinnrry
        39
    Jinnrry  
       52 天前 via Android
    你可以试试 map any any

    不过建议你写 php
    qW7bo2FbzbC0
        40
    qW7bo2FbzbC0  
    OP
       52 天前
    同样是使用匿名类型去序列化,c#正确识别出了 Number 类型

    ```c#
    // See https://aka.ms/new-console-template for more information
    using System.Text.Json;
    using MySqlConnector;


    using var connection = new MySqlConnection("Server=127.0.0.1;User ID=root;Password=****;Database=test");
    connection.Open();

    using var command = new MySqlCommand("select id from t1;", connection);
    using var reader = command.ExecuteReader();
    var x = new Dictionary<string, object> { };
    while (reader.Read())
    {
    x["name"] = "name";
    x["value"] = reader.GetValue(0);
    }
    Console.WriteLine(JsonSerializer.Serialize(x));
    ```

    输出结果为

    ```js
    {"name":"name","value":1}
    ```
    jsonparse
        41
    jsonparse  
       52 天前
    建议用 python
    HanSonJ
        42
    HanSonJ  
       52 天前
    可以用 gjson
    NessajCN
        43
    NessajCN  
       52 天前
    @qW7bo2FbzbC0 不然列,[]byte 本来就已经是 byte array 了,你再把他序列化一遍想变成啥?
    vczyh
        44
    vczyh  
       52 天前
    sql.RawBytes 就是[]byte, []byte 序列化 json 的时候就是应该使用 base64 ,不然控制字符怎么打印?你不能认为都是[]byte{97, 98} ab 这种可打印字符。

    不符合你的预期而已,你都用[]byte 接收据了,类型肯定丢失了。
    elevioux
        45
    elevioux  
       52 天前
    life is short , use php
    james122333
        46
    james122333  
       52 天前
    @qW7bo2FbzbC0

    package main

    import(
    "encoding/json"
    )

    func main() {
    m := map[string]any {
    "name": "name",
    "value": 1,
    }
    b, _ := json.Marshal(m)
    println(string(b))
    }

    {"name":"name","value":1}
    kkk9
        47
    kkk9  
       52 天前   ❤️ 2
    惯性思维、学艺不精
    wysnxzm
        48
    wysnxzm  
       52 天前
    总结:go 没问题,是你不会自适应
    james122333
        49
    james122333  
       52 天前
    package main

    import(
    "encoding/json"
    )

    func main() {
    m := map[string]any {
    "name": "name",
    "value": json.RawMessage([]byte("1")),
    }
    b, _ := json.Marshal(m)
    println(string(b))
    }

    {"name":"name","value":1}
    lysShub
        50
    lysShub  
       52 天前
    看你的需求,直接存 string 字符串,查询的时候用 gjson 读。当然这样性能和安全就下降了一个层次
    james122333
        51
    james122333  
       52 天前
    @qW7bo2FbzbC0

    我已经回了 n 次 json.RawMessage...
    lesismal
        52
    lesismal  
       52 天前
    定义跟 sql table 对应的 struct 是必要的, 自动绑定后用 json 去操作 struct 就没这个问题了.
    个人觉得 orm 不好用, 自己搞了份 raw sql+自动绑定的库, 有兴趣可以试试, 例子:
    https://github.com/lesismal/sqlw_examples/blob/main/mysql/db/db.go#L101
    james122333
        53
    james122333  
       52 天前 via Android
    @lesismal

    你写的这个楼主说的 sqlx 已经有了
    然后我在公司又把它封装成无 join 功能的 orm
    xFrye
        54
    xFrye  
       52 天前   ❤️ 4
    我觉得用一门语言的原则是用他的推荐方式去实现代码,而不是想着怎么这垃圾语言没法像谁谁那样写。。。
    skuuhui
        55
    skuuhui  
       52 天前
    interface{}
    qW7bo2FbzbC0
        56
    qW7bo2FbzbC0  
    OP
       52 天前
    同样是使用匿名类型去序列化,java 也正确识别出了 Number 类型
    ```java
    package com.test.Demo;

    import java.sql.*;
    import java.io.*;
    import java.util.*;
    import com.google.gson.*;

    public class Demo {
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    static final String USER = "root";
    static final String PASS = "******";

    public static void main(String[] args) {
    Connection conn = null;
    Statement stmt = null;
    try{
    Class.forName(JDBC_DRIVER);
    conn = DriverManager.getConnection(DB_URL,USER,PASS);
    stmt = conn.createStatement();
    String sql = "select id from t1";
    ResultSet rs = stmt.executeQuery(sql);
    HashMap<String, Object> x;
    x = new HashMap<String, Object>();

    while(rs.next()){
    Object id = rs.getObject("id");
    x.put("name", "name");
    x.put("value", id);
    }
    Gson gson = new Gson();
    System.out.println(gson.toJson(x));
    } catch (Exception e){
    e.printStackTrace();
    }

    }

    }

    ```
    pkoukk
        57
    pkoukk  
       52 天前
    map[string]any
    然后根据你说的,某个标识字段,判断类型,再用 https://github.com/mitchellh/mapstructure
    转成你要的实际 struct
    ScepterZ
        58
    ScepterZ  
       52 天前
    这是 sql 库返回的对象不好序列化的问题,不是 json 库的问题,要解决的话也应该是 sql 库这边来处理,给一个方便打印的办法
    qW7bo2FbzbC0
        59
    qW7bo2FbzbC0  
    OP
       52 天前
    @james122333 json.RawMessage 是可行的,但是看起来和 java/c#的模式不同,从 go/sql 映射出来的 interface 变成了[]byte 而不是(interface).type ,而且官方文档好像也推荐用 interface 或者 sql.RawBytes 来接未知类型
    qW7bo2FbzbC0
        60
    qW7bo2FbzbC0  
    OP
       52 天前
    @ScepterZ 是的,我说错了,是 go/sql 返回的 interface 无法直接序列化
    veni2023
        61
    veni2023  
       52 天前
    @pkoukk 遇到过这个包在弱类型解析时有精度丢失的情况
    houzhiqiang
        62
    houzhiqiang  
       52 天前
    我猜想要的效果是这样的:
    ```python
    import pymysql
    import pymysql.cursors


    connect = pymysql.connect(
    host="example.com", port=3306, user="user", password="password", database="database_name",
    cursorclass=pymysql.cursors.DictCursor,
    )
    with connect.cursor() as cursor:
    cursor.execute(
    """select * from users limit %(param_limit)s""",
    args={"param_limit": 2}
    )
    results = cursor.fetchall()
    print(results)
    # [
    # {'id': 13, 'birthday': datetime.date(1900, 1, 1), 'create_time': datetime.datetime(2020, 9, 3, 16, 56, 39)},
    # {'id': 39, 'birthday': datetime.date(1900, 1, 1), 'create_time': datetime.datetime(2020, 9, 14, 17, 5, 1)}
    # ]
    ```
    vczyh
        63
    vczyh  
       52 天前
    @qW7bo2FbzbC0

    func TestMy(t *testing.T) {
    db, err := sql.Open("mysql", "root:123@/test")
    if err != nil {
    t.Fatal(err)
    }
    defer db.Close()

    rows, err := db.Query("SELECT id FROM t1")
    if err != nil {
    t.Fatal(err)
    }

    for rows.Next() {
    var id any
    if err := rows.Scan(&id); err != nil {
    t.Fatal(err)
    }
    m := map[string]any{
    "value": id,
    }
    b, err := json.Marshal(m)
    if err != nil {
    t.Fatal(err)
    }
    t.Log(string(b))
    }
    if err := rows.Err(); err != nil {
    t.Fatal(err)
    }
    }

    {"value":1}


    用 any 接收数据,返回的类型由驱动实现决定,database/sql 只提供接口,驱动负责返回 sqldriver.Value ,所以真不是 Go 语言的问题。
    jlkm2010
        64
    jlkm2010  
       52 天前
    go 的语法很怪异
    kkbblzq
        65
    kkbblzq  
       52 天前
    这跟 json 都没有关系,而是 sql 类型和 go 类型之间的转换问题。
    qW7bo2FbzbC0
        66
    qW7bo2FbzbC0  
    OP
       52 天前
    @vczyh 你这个是什么驱动?
    vczyh
        67
    vczyh  
       52 天前
    vczyh
        68
    vczyh  
       52 天前
    lesismal
        69
    lesismal  
       52 天前
    @james122333
    1. orm 是非常不好的选择, 中小项目倒是还可以, 大项目大数据量的, 用 orm 存在一些不确定性可能导致性能风险, 所以我都是禁止团队试用 golang orm 的
    2. 还有生成代码的 sqlc 这种, 性能当然是最友好但用起来也有点麻烦, 因为一些业务是上下文比较复杂的, 单纯生成一段 sql 对应的 go 代码还需要 ctrl cv 而且还要修改对应的地方, 功能修改的时候比较麻烦
    3. sqlx 简化了一些 binding, 但也把一些简单的复杂化了, 比如又有 Select 又有 Get, 比如 Insert 缺少 struct 的自动绑定(我没深入使用只是看它文档和例子), 综合下来我觉得它少了一些可以真正节约体力的但多了不少没必要的, 所以对我来说病不好用

    所以以前还是继续标准库 raw sql, 直到我实在忍不了标准库 raw sql 自己搞了这个
    lifei6671
        70
    lifei6671  
       52 天前
    @qW7bo2FbzbC0 #37 没看到别人扣帽子,反而是你自己情绪化,人家都说了你用不惯 go 就换成你喜欢的语言好了,再说了,interface 满天飞就是犯懒的行为。
    qW7bo2FbzbC0
        71
    qW7bo2FbzbC0  
    OP
       52 天前
    @lifei6671 1.8 之前还有什么办法避免 Interface 满天飞?
    lesismal
        72
    lesismal  
       52 天前
    @james122333 我这个就是简简单单几点:
    1. 鼓励明确定义 table 对应的 struct, 用明确定义的 struct 操作 sql, 这个 struct 自己手写也好用工具生成也好, 都挺方便的
    2. 鼓励 raw sql, 避免 orm 之类的可能生成了性能不友好的语句造成性能事故
    3. 框架尽量自动映射/绑定 sql table 和 struct, insert/update/select 这些与 struct 映射绑定操作密切的都很轻松用 struct 操作
    4. 奥卡姆剃刀原则, 不提供 orm, 不提供那么多没什么必要的垃圾接口
    fregie
        73
    fregie  
       52 天前
    @qW7bo2FbzbC0 "我觉得 go/sql 和 json.Marshal 对于匿名类型查询不友好也是犯懒?"
    不友好的意思是指不能用方便又稳定的办法解决这个问题,只能用麻烦但是稳定的方式解决.
    你认为这不友好难道不是犯懒吗?
    BTW,何必这么敏感,犯懒又不是什么攻击性的词语,我自己也经常犯懒,人皆是如此,只是要可能会付出代价
    这个世界还是挺美好的,没必要一进入互联网就进入攻击模式
    superrichman
        74
    superrichman  
       52 天前
    @zxdstyle 你想表达的是动态语言和静态语言的区别
    qW7bo2FbzbC0
        75
    qW7bo2FbzbC0  
    OP
       52 天前
    @fregie 犯懒字面上是贬义词吧,你觉得不是攻击性的,那你可以自己多读几遍,不要替别人做决定。稳定不稳定不知道,写起来麻烦的代码后面维护起来肯定更麻烦
    lesismal
        76
    lesismal  
       52 天前
    @qW7bo2FbzbC0 #71
    interface 满天飞是当时写这些垃圾代码的人的问题, 不是 golang 自己的问题.
    正确姿势本来就应该避免 interface 满天飞, 我看到很多喜欢搞 interface 满天飞的, 是 php nodejs 之类的转 go 的人居多, 这也不能全怪他们, 毕竟以前语言习惯已经信手拈来了, 刚开始未必能意识到这样会带来工程上的问题, 更何况有时候赶工只追求先搞定业务
    c/cpp 或者一些新手上路就是 go 的, 姿势正常的人多些

    接手别人的屎山不是 OP 的错, interface 满天飞不是 golang 的错, OP 要怪就都怪写屎山的人吧
    leonshaw
        77
    leonshaw  
       52 天前
    用 ScanType 反射?
    iyaozhen
        78
    iyaozhen  
       52 天前
    用 go 千万不要和别的语音比 不要之前语言思维定势。不然坑还更多
    qW7bo2FbzbC0
        79
    qW7bo2FbzbC0  
    OP
       52 天前
    按楼上说的 json.RawMessage 解决了,我没有想到要去 json 命名空间里找类型
    @leonshaw
    james122333
        80
    james122333  
       52 天前
    @qW7bo2FbzbC0

    这你要问 driver 为什么输出的格式是[]byte 也就是你上面贴的那个 lib
    目前没时间研究 你自立自强点
    至於 json 对[]byte 处理是合理的
    james122333
        81
    james122333  
       52 天前   ❤️ 1
    @lesismal

    我目前弄的只有简单的 crud 和建立表 join 没整其他指令也没整 还是基於 sqlx 整的 只是用原生的 sql 应该也都差不多
    根据 struct 中 tag 讯息拼接字符串 反射方法都已经写好 验证下来没问题 会这样搞主要是想偷懒点
    fregie
        82
    fregie  
       52 天前
    @qW7bo2FbzbC0 嫌麻烦而想放弃,这不是犯懒?
    gowk
        83
    gowk  
       52 天前
    回帖不支持代码,,看着就非常难受!
    zzhaolei
        84
    zzhaolei  
       52 天前
    show me the code
    lloovve
        85
    lloovve  
       52 天前 via iPhone
    这边建议转 rust 试试
    woodfizky
        86
    woodfizky  
       52 天前
    Python 是强类型语言,不管用 ORM 还是原生 SQL 一样要处理类型问题。

    不懂某些评论为什么要说有 Python 味,吐槽之前好好调查一下再给出观点很难是吗?
    zzhaolei
        87
    zzhaolei  
       52 天前
    @lesismal
    “1. orm 是非常不好的选择, 中小项目倒是还可以, 大项目大数据量的, 用 orm 存在一些不确定性可能导致性能风险, 所以我都是禁止团队试用 golang orm 的”

    这一点可以举例说明:有哪些不确定性可能导致性能风险吗

    我现在在公司用的就是 GORM ,想了解一下
    knva
        88
    knva  
       52 天前
    go 的 sql set 0 的问题太带劲了
    qW7bo2FbzbC0
        89
    qW7bo2FbzbC0  
    OP
       52 天前
    @fregie 你满意就好
    boqiqita
        90
    boqiqita  
       52 天前
    幸好不会用 java 、C#、C 、C++
    XyIsMy
        91
    XyIsMy  
       52 天前
    @zzhaolei @lesismal grom 可以设置 Logger level 在开发过程中就可以看到执行的 sql ,有问题能直接发现。gorm 也有 raw sql 模式可以直接用。
    是在使用 GROM 中踩了哪些坑么。如果有坑的话,我需要重新考虑下要不要用 gorm
    picone
        92
    picone  
       52 天前
    Go 使用 json.RawMessage 也可以达到你说的效果,不会变成 base64
    zzhaolei
        93
    zzhaolei  
       52 天前
    @XyIsMy 我是这么用的。

    我就是好奇,这些人张嘴闭嘴就是 ORM 有不确定性,到底有什么不确定性,自己测试过?还是踩过坑?还是说嘴一张一闭反正我不管,ORM 就是有性能问题?

    我之前进行过性能测试,如果 GORM 那些事务什么的全都关了,是会比原生 SQL 慢一些,但是没有慢特别多。至今没有踩过什么坑。
    james122333
        94
    james122333  
       52 天前
    @zzhaolei

    orm 本身没有不确定性 本质还是产生 query string 传参 orm 的不确定性在於框架的实现 太过细节的框架从另外角度讲是坑
    gorm 确实是慢没错 更何况就是要用事务
    我离职了再写一个比较好的自己用
    qW7bo2FbzbC0
        95
    qW7bo2FbzbC0  
    OP
       52 天前
    各位,我比对了下,[]interface{}没有被 json.Marshal 出正确的数值和类型,是与我用的 go-mysql-driver 版本有关。

    1.6.0 版本是出现了与我预测不同的结果。1.8 版本出现了预测的结果

    json.Marshal 可能与本次贴文无直接关系。

    另外,我觉得问题出自 json.Marshal 是从这个 sof 链接中的评论得到的错误推论,的确有迷惑性( https://stackoverflow.com/questions/34089750/marshal-byte-to-json-giving-a-strange-string)


    ```
    This is because some idiot Millennial at Google decided it. Breaking the behaviour the RFC their JSON impl claims to follow defines. Check stackoverflow.com/a/78662958/3768429 for details.
    ```

    该文指出 json.Marshal 处理 uint8[]时,错误输出了文字, 验证代码如下
    ```
    func main() {
    var x = []uint8{1, 2, 3, 4, 5, 6}
    var y = []int8{1, 2, 3, 4, 5, 6}
    xBytes, err := json.Marshal(x)
    if err != nil {
    panic(err)
    }
    yBytes, err := json.Marshal(y)
    if err != nil {
    panic(err)
    }
    fmt.Println(fmt.Sprintf("uint8 %s, int8: %s", string(xBytes), string(yBytes)))
    }
    ```
    输出的结果为
    ```
    uint8 "AQIDBAUG", int8: [1,2,3,4,5,6]
    ```

    https://go.dev/play/p/KGNG6voRuDk
    sagaxu
        96
    sagaxu  
       52 天前
    @zzhaolei @XyIsMy

    ORM 的不确定性往往不是出自 ORM 本身,而是使用者的不确定性,大部分人只是会用,并不全面了解,有些时候会遇到令人惊讶的特性,其中不少人会专门写踩坑博文。
    qW7bo2FbzbC0
        97
    qW7bo2FbzbC0  
    OP
       52 天前
    @james122333 您是对的,这的确和 json.Marshal 没关系,是 go-mysql-driver 的问题。

    https://github.com/go-sql-driver/mysql/pull/1424
    james122333
        98
    james122333  
       52 天前
    @qW7bo2FbzbC0

    vczyh 先讲这问题的 后面才看到 你要先感谢他
    james122333
        99
    james122333  
       52 天前 via Android
    @qW7bo2FbzbC0

    我有跳转过去 go 底层看就是 基本类型应该都有函盖才对 所以推测 driver 问题 不过没验过 对照一下 vczyh 的说明应该是这样
    ClericPy
        100
    ClericPy  
       52 天前
    以前是用别的语言的吧,我记得有个库可以用比原生的优雅一点,不习惯的话要不要问问别人怎么用的再来吐槽

    话说对于 JSON 解析如果没啥特殊需求,大多数语言都有 jmespath 的分支吧,以前用 py 的版本发现性能秒杀同类 jsonpath/objectpath 而且语法也简单,没必要自己硬抠嵌套结构,json-handler 一开直接提取路径了
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1187 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 23:58 · PVG 07:58 · LAX 16:58 · JFK 19:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.