V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
szxczyc
V2EX  ›  问与答

[求助]MySQL 存了 json 怎么样才能读出正确的 json 格式?

  •  
  •   szxczyc · 2021-11-27 17:36:49 +08:00 · 2038 次点击
    这是一个创建于 1127 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天晚上到今天下午,查了快一天百度也没找到解决办法~人已经崩溃了~ 用的 Gorm 处理~对 Go 也不太熟悉~感觉这搞来搞去真的要高血压了~

    首先,我拿到了一个 json ,长这样:

    {
        "version": "0.0.1",
        "success": true,
        "result": [
            {
                "service_tag": "12345T",
                "ip_lan": "10.10.10.10",
                "ip_wan": "0.0.0.0",
                "idc": "MH",
                "tags": [
                    {
                        "tag_category": "environment",
                        "value": "live"
                    },
                    {
                        "tag_category": "idc",
                        "value": "sg"
                    },
                    {
                        "tag_category": "application",
                        "value": "stoc"
                    },
                    {
                        "tag_category": "function",
                        "value": "redis"
                    },
                    {
                        "tag_category": "server_standard",
                        "value": "S1"
                    },
                    {
                        "tag_category": "office",
                        "value": "SG"
                    }
                ],
                "memory": "1250GB",
                "cpu_count": 4800,
                "state": "operating"
            }
        ]
    }
    

    随后我把 JSON 的 tags 标签存到了 mysql 中,长这样:

    [{"tag_category":"environment","value":"live"},{"tag_category":"idc","value":"sg"},{"tag_category":"application","value":"stoc"},{"tag_category":"function","value":"redis"},{"tag_category":"server_standard","value":"S1"},{"tag_category":"office","value":"SG"}]
    

    到这里都没有什么问题,可是我通过 mysql 自带的查询语句查所有数据的时候,查出的并不是 json 格式了~ tags 的内容被当成了字符串,被加了前缀"和后缀",内容中也含有转义字符\

    {
        "version": "0.0.1",
        "success": true,
        "result": [
            {
                "ID": 1,
                "ServiceTag": "test",
                "IPLan": "10.10.10.11",
                "IPWan": "0.0.0.0",
                "Idc": "SZ",
                "State": "",
                "Memory": "128GB",
                "CpuCount": 48,
                "Tags": "test",
                "CcUName": "",
                "CcService": "",
                "CreatedAt": 1231,
                "UpdatedAt": 1637956306,
                "PState": "已完成 11111"
            },
            {
                "ID": 2,
                "ServiceTag": "123456T",
                "IPLan": "10.10.10.10",
                "IPWan": "0.0.0.0",
                "Idc": "BJ",
                "State": "operating",
                "Memory": "125GB",
                "CpuCount": 48,
                "Tags": "[{\"tag_category\":\"environment\",\"value\":\"live\"},{\"tag_category\":\"idc\",\"value\":\"sg\"},{\"tag_category\":\"application\",\"value\":\"stoc\"},{\"tag_category\":\"function\",\"value\":\"redis\"},{\"tag_category\":\"server_standard\",\"value\":\"S1\"},{\"tag_category\":\"office\",\"value\":\"SG\"}]",
                "CcName": "",
                "CcService": "",
                "CreatedAt": 1638005233,
                "UpdatedAt": 1638005233,
                "PState": "未解决"
            }
        ]
    }
    
    14 条回复    2021-11-28 15:52:57 +08:00
    ysc3839
        1
    ysc3839  
       2021-11-27 20:08:49 +08:00 via Android
    你给的 Tags 就是很标准的 JSON 字符串呀,大概是 MySQL 原生不支持 JSON ,所以先转成了 JSON 字符串再存储。
    lululau
        2
    lululau  
       2021-11-27 20:19:00 +08:00
    没有问题

    mysql> desc json_demo;
    +---------+---------+------+-----+---------+----------------+
    | Field | Type | Null | Key | Default | Extra |
    +---------+---------+------+-----+---------+----------------+
    | id | int(11) | NO | PRI | NULL | auto_increment |
    | content | json | YES | | NULL | |
    +---------+---------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)

    mysql> insert into json_demo (content) values ('{"title": "test"}');
    Query OK, 1 row affected (0.00 sec)

    mysql> select * from json_demo;
    +----+-------------------+
    | id | content |
    +----+-------------------+
    | 2 | {"title": "test"} |
    +----+-------------------+
    1 row in set (0.00 sec)
    iseki
        3
    iseki  
       2021-11-27 21:07:31 +08:00
    贴出操作用的 sql 呗
    djFFFFF
        4
    djFFFFF  
       2021-11-27 22:18:18 +08:00
    mysql 的表结构是什么;你的 go 代码怎么写的,这两个不给出来,没法查。
    yuzo555
        5
    yuzo555  
       2021-11-27 22:21:16 +08:00
    JSON 本来就相当于可操作的字符串,你自己再解析成 JSON 就行了呀
    lagoon
        6
    lagoon  
       2021-11-27 23:09:37 +08:00
    手动把\过滤掉。

    我是 app 开发,遇到过这种情况。
    后台直接存的 json ,后来拿出来的时候,都带有转移字符了。

    很多人以为\",是转义字符没有错。
    但其实,拿出来的是\\",转义之后是\"


    当然,我也遇到过非说没问题,让前端自己处理的后端。
    cwr31
        7
    cwr31  
       2021-11-27 23:23:22 +08:00 via iPhone
    mysql 支持 json 的 不要用字符串存
    szxczyc
        8
    szxczyc  
    OP
       2021-11-27 23:45:42 +08:00
    @lagoon 手动的话该怎么处理呢?感觉这似乎不太可行啊~方便说一下嘛?
    szxczyc
        9
    szxczyc  
    OP
       2021-11-27 23:46:19 +08:00
    @cwr31 用 JSON 存储的话,取出来的数据\前面还有一个空格~更不好处理了
    zyxk
        10
    zyxk  
       2021-11-28 01:00:08 +08:00
    直接读取后,自己把 json str 转换为 json obj 或 struct 使用就行了,
    如果 mysql 自动转换的 json 格式不标准的话, 存之前自己转换成 str 再存不就行了.
    ProphetN
        11
    ProphetN  
       2021-11-28 01:25:39 +08:00
    Java 里遇到过,Gson 可以直接转成实体类,不用再处理一次。
    szxczyc
        12
    szxczyc  
    OP
       2021-11-28 02:50:25 +08:00
    @djFFFFF go 的表中有一列 tags 存储 JSON 的 tags 标签( varchar(1000)),查询语句用的是 gorm 的 FIND 方法,查询整个库,其他都是字符串显示正常,但是存 JSON 的 tags 标签的这部分直接被当成了字符串了。
    func (db *serverlistDB) GetAll() ([]*ServerList, error) {
    ServerLists := make([]*ServerList, 0)
    tx := db.Find(&ServerLists)
    return ServerLists, tx.Error
    }
    @iseki
    djFFFFF
        13
    djFFFFF  
       2021-11-28 13:34:11 +08:00
    @szxczyc 有几个点需要确认。
    一个是你这张表的 mysql 的字段是什么,是 json 还是 varchar 还是别的
    一个是你这个 ServerList 的定义里,gorm 部分的标签是怎么写的。
    另一个是,gorm 的 json 字段,如果是自定义类型,都需要实现一个 Scan(value interface{}) error 和一个 Value() (driver.Value, error) 方法,gorm 才能知道如何从 json 转成对应的数据结构。详见 https://gorm.io/docs/data_types.html 这个文档。
    举个 map[string]string 的例子:

    type SomeJsonField map[string]string

    func (i *SomeJsonField) Scan(value interface{}) error {
    bytes, _ := value.([]byte)

    err := json.Unmarshal(bytes, i)
    return err
    }

    func (i SomeJsonField) Value() (driver.Value, error) {
    return json.Marshal(i)
    }
    szxczyc
        14
    szxczyc  
    OP
       2021-11-28 15:52:57 +08:00
    @djFFFFF 非常非常感谢~我按照您的方法已经解决了这个问题了~感谢感谢!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2607 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 03:37 · PVG 11:37 · LAX 19:37 · JFK 22:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.