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

2021-11-27 17:36:49 +08:00
 szxczyc

昨天晚上到今天下午,查了快一天百度也没找到解决办法~人已经崩溃了~ 用的 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": "未解决"
        }
    ]
}
1870 次点击
所在节点    问与答
14 条回复
ysc3839
2021-11-27 20:08:49 +08:00
你给的 Tags 就是很标准的 JSON 字符串呀,大概是 MySQL 原生不支持 JSON ,所以先转成了 JSON 字符串再存储。
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
2021-11-27 21:07:31 +08:00
贴出操作用的 sql 呗
djFFFFF
2021-11-27 22:18:18 +08:00
mysql 的表结构是什么;你的 go 代码怎么写的,这两个不给出来,没法查。
yuzo555
2021-11-27 22:21:16 +08:00
JSON 本来就相当于可操作的字符串,你自己再解析成 JSON 就行了呀
lagoon
2021-11-27 23:09:37 +08:00
手动把\过滤掉。

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

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


当然,我也遇到过非说没问题,让前端自己处理的后端。
cwr31
2021-11-27 23:23:22 +08:00
mysql 支持 json 的 不要用字符串存
szxczyc
2021-11-27 23:45:42 +08:00
@lagoon 手动的话该怎么处理呢?感觉这似乎不太可行啊~方便说一下嘛?
szxczyc
2021-11-27 23:46:19 +08:00
@cwr31 用 JSON 存储的话,取出来的数据\前面还有一个空格~更不好处理了
zyxk
2021-11-28 01:00:08 +08:00
直接读取后,自己把 json str 转换为 json obj 或 struct 使用就行了,
如果 mysql 自动转换的 json 格式不标准的话, 存之前自己转换成 str 再存不就行了.
ProphetN
2021-11-28 01:25:39 +08:00
Java 里遇到过,Gson 可以直接转成实体类,不用再处理一次。
szxczyc
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
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
2021-11-28 15:52:57 +08:00
@djFFFFF 非常非常感谢~我按照您的方法已经解决了这个问题了~感谢感谢!!!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/818385

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX