iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >MySQL存储Json字符串遇到的问题与解决方法
  • 713
分享到

MySQL存储Json字符串遇到的问题与解决方法

2024-04-02 19:04:59 713人浏览 独家记忆
摘要

目录环境依赖问题描述原因分析解决方案方案一 转义符替换方案二 修改sql书写方式方案三 DataFrame.to_sql()补充:不同情况总结环境依赖 python 2.7Mysql

环境依赖

python 2.7
Mysql 5.7
mysql-Python 1.2.5
pandas 0.18.1

在日常的数据处理中,免不了需要将一些序列化的结果存入到MySQL中。这里以插入JSON数据为例,讨论这种问题发生的原因和解决办法。现在的MySQL已经支持jsON数据格式了,在这里不做讨论;主要讨论如何保证存入到MySQL字段中的JsonString能被正确解析。

问题描述

# -*- coding: utf-8 -*-
import MySQLdb
import json

mysql_conn = MySQLdb.connect(host='localhost', user='root', passwd='root', db='test', port=3306, charset='utf8')
mysql_cur = mysql_conn.cursor()

increment_id = 1
dic = {"value": "<img src=\"xxx.jpg\">", "name": "小明"}
json_str = json.dumps(dic, ensure_ascii=False)

sql = "update demo set msg = '{0}' where id = '{1}'".fORMat(json_str, increment_id)
mysql_cur.execute(sql)
mysql_conn.commit()
mysql_cur.close()

应用场景抽象如上所示,将一个字典经过经过Json序列化后作为一个表字段的值存入到Mysql中,按照如上的方式更新数据时,发现落库的JsonString反序列化失败;落库结果和反序列化结果分别如下所示:

原因分析

对于字符串中包含引号等其他特殊符号的处理思路在大多数编程语言中都是相通的:即就是通过转义符来保留所需要的特殊字符。Python中也不例外,如上所示,对于一个字典{"value": "<img src="xxx.jpg">", "name": "小明"},要想在编译器里正确的表示它,就需要通过对转义包裹xxx.jps的两个双引号,不然会提示错误,所以它的正确写法为:{"value": "<img src=\"xxx.jpg\">", "name": "小明"};将序列化后的String作为参数传入待执行的sql语句中,通过编辑器的debug模式查看的效果如下所示:

而这句sql经过编译器解析后传入到MySQL去执行的本质为:'update demo set msg = '{"source": "<img src="xxx.jpg">", "type": "图片"}' where id = '1',因此落库的实际结果其实并不是目标字典对应的序列化结果,而是目标数据对应的字面字符串值。

解决方案

可以通过转义符替换、修改sql书写方式或通过DataFrame.to_sql()三种方式来解决。

方案一 转义符替换

通过上文可以了解到,是因为\\"xxx.jpg\\"的本质即就是"xxx.jpg",所以数据库读到的也就是{"source": "<img src="xxx.jpg">", "type": "图片"},从而导致插入的结果并不能被正确反序列化。可以通过简单粗暴的转义符替换方式来解决这个问题:json_str.replace('\\', '\\\\'),这样就保证最终的解析结果为\"xxx.jpg\"

方案二 修改sql书写方式

  def execute(self, query, args=None):
        del self.messages[:]
        db = self._get_db()
        if isinstance(query, unicode):
            query = query.encode(db.unicode_literal.charset)
        if args is not None:
            # 通过调用内置的解析函数literal,将目标参数按照原义解析
            # 解析的依据详见源码的MySQLdb.converters
            if isinstance(args, dict):
                query = query % dict((key, db.literal(item))
                                     for key, item in args.iteritems())
            else:
                query = query % tuple([db.literal(item) for item in args])
        try:
            r = None
            r = self._query(query)
        except TypeError, m:
            if m.args[0] in ("not enough arguments for format string",
                             "not all arguments converted"):
                self.messages.append((ProgrammingError, m.args[0]))
                self.errorhandler(self, ProgrammingError, m.args[0])
            else:
                self.messages.append((TypeError, m))
                self.errorhandler(self, TypeError, m)
        except (SystemExit, KeyboardInterrupt):
            raise
        except:
            exc, value, tb = sys.exc_info()
            del tb
            self.messages.append((exc, value))
            self.errorhandler(self, exc, value)
        self._executed = query
        if not self._defer_warnings: self._warning_check()
        return r

查看MySQL-python的execute源码(如上所示)可以发现,在传入待执行的sql语句的同时,还可以传入参数列表/字典;让MySQL-Python来帮我们进行sql语句的拼接和解析操作,修改上述样例的实现方式:

increment_id = 1
dic = {"value": "<img src=\"xxx.jpg\">", "name": "小明"}
json_str = json.dumps(dic, ensure_ascii=False)

sql = "update demo set msg = %s where id = %s"
mysql_cur.execute(sql, [json_str, increment_id])
mysql_conn.commit()
mysql_cur.close()

通过走读源码发现参数经过literal()方法将Python的对象转化为对应SQL数据的字符串格式;在编译器Debug模式下可以看到最终将\\"xxx.jpg\\"转化为\\\\\\"xxx.jpg\\\\\\"。至于为什么是六个反斜杠我自己也不太清楚;不过姑且可以这样理解:把literal方法的操作可以假定为有一次的序列化,因为给定的数据源是\",所以序列化的结果为应该为\\",即就是四个反斜杠;因为\“代表的即就是”,而期望落库的结果为",所以需要再添加两个反斜杠。这种解释不是那么准确和严谨,但是有利于帮助理解,若有了解底层机制和原理的,还请留言指教。

推荐使用

方案三 DataFrame.to_sql()

处理数据离不开Panda工具包;Pandas的DataFrame.to_sql()方法可以便捷有效的实现数据的插入需求;同样该方法也能有效的规避上述这种序列化结果错误的情况,因为DataFrame.to_sql()底层的实现逻辑类似于方案二,也是通过参数解析的方式来拼接sql语句,核心源码如下所示,同于不难发现,DataFrame.to_sql()只能支持insert操作,适用场景比较局限。对于有唯一索引的表,当待插入数据与数据表中有冲突时会报错,实际使用时需要格外注意。

def insert_statement(self):
        names = list(map(text_type, self.frame.columns))
        flv = self.pd_sql.flavor
        wld = _SQL_WILDCARD[flv]  # wildcard char
        escape = _SQL_GET_IDENTIFIER[flv]

        if self.index is not None:
            [names.insert(0, idx) for idx in self.index[::-1]]

        bracketed_names = [escape(column) for column in names]
        col_names = ','.join(bracketed_names)
        wildcards = ','.join([wld] * len(names))
        # 只支持Insert操作
        insert_statement = 'INSERT INTO %s (%s) VALUES (%s)' % (
            escape(self.name), col_names, wildcards)
        return insert_statement

补充:

补充:不同情况

1.模糊查询json类型字段

存储的数据格式(字段名 people_json):

{“name”: “zhangsan”, “age”: “13”, “gender”: “男”}

代码如下(示例):

select * from table_name  where people_json->'$.name' like '%zhang%'

2.精确查询json类型字段

存储的数据格式(字段名 people_json):

{“name”: “zhangsan”, “age”: “13”, “gender”: “男”}

代码如下(示例):

select * from table_name  where people_json-> '$.age' = 13

3.模糊查询JsonArray类型字段

存储的数据格式(字段名 people_json):

[{“name”: “zhangsan”, “age”: “13”, “gender”: “男”}]

代码如下(示例):

select * from table_name  where people_json->'$[*].name' like '%zhang%'

4.精确查询JsonArray类型字段

存储的数据格式(字段名 people_json):

[{“name”: “zhangsan”, “age”: “13”, “gender”: “男”}]

代码如下(示例):

select * from table_name  where JSON_CONTAINS(people_json,JSON_OBJECT('age', "13"))

总结

到此这篇关于MySQL存储Json字符串遇到的问题与解决方法的文章就介绍到这了,更多相关MySQL存储Json字符串内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL存储Json字符串遇到的问题与解决方法

本文链接: https://www.lsjlt.com/news/164570.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL存储Json字符串遇到的问题与解决方法
    目录环境依赖问题描述原因分析解决方案方案一 转义符替换方案二 修改sql书写方式方案三 DataFrame.to_sql()补充:不同情况总结环境依赖 Python 2.7MySQL...
    99+
    2024-04-02
  • mysql存储不了中文字符串的解决方法
    小编给大家分享一下mysql存储不了中文字符串的解决方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!mysql存储不了中文字符...
    99+
    2024-04-02
  • json字符串乱序问题怎么解决
    解决 JSON 字符串乱序问题的方法主要有两种: 使用 JSON.stringify() 方法和自定义排序函数对 JSON 对象进...
    99+
    2024-03-01
    json
  • 解决JSON.parse转化不规范json字符串的问题
    目录JSON.parse转化不规范json字符串问题1 json字符串中的key值没有带引号2 json字符串中的key值带的单引号3 规范的json字符串格式4 不规范json字符...
    99+
    2024-04-02
  • 解决json字符串序列化后的顺序问题
    1、应用场景: 如果项目中用到json字符串转为jsonObject的需求,并且,需要保证字符串的顺序转之前和转成jsonObject之后输出的结果完全一致。可能有点绕口,下面举一个...
    99+
    2024-04-02
  • C++中字符串处理问题的解决方法
    C++中字符串处理问题的解决方法概述:在C++编程中,字符串的处理是一个常见的问题,涉及到字符串的截取、拼接、查找、替换等操作。本文将介绍几种常用的解决方法,并提供具体的代码示例。一、字符串截取字符串截取是指从一个字符串中获取一部分子串。在...
    99+
    2023-10-22
    C++ 解决方法 字符串处理
  • 解决MongoDB技术开发中遇到的数据存储问题的方法研究
    解决MongoDB技术开发中遇到的数据存储问题的方法研究摘要:随着大数据时代的到来,数据存储与处理成为了技术开发中的重要环节。MongoDB作为一种非关系型数据库,具有强大的数据存储和处理能力,但在实际开发中也存在一些问题。本文将研究并提出...
    99+
    2023-10-22
    MongoDB 数据存储 问题解决方法
  • Mysql直接查询存储的Json字符串中的数据
    我们平时使用mysql,出于项目需求,可能需要直接将Java对象或者一个大json,直接存到表中的某个字段中;使用的时候再查出来,反序列化到对象或者一个Map中,方便我们操作; 大多...
    99+
    2024-04-02
  • mysql 部分字符存储报错 Incorrect string value问题解决
    原因分析 正常情况 utf-8 是一种可变长度的字符集,它的单个字符的长度范围可以在1~4字节之间变化。由于其支持字符范围广并且传输效率高而被广泛使用。虽然在 Windows 中我们默认用的还是 gbk字符集 ,但是在使用浏览器浏览网站的时...
    99+
    2023-09-05
    mysql java 数据库
  • redis字符串存储的方法是什么
    Redis字符串存储的方法主要有以下几种:1. SET:设置指定 key 的值为字符串。如果 key 已经存在,则覆盖原来的值。2....
    99+
    2023-09-11
    redis
  • PHP开发中遇到的16进制转字符串中文乱码问题及解决方案
    PHP开发中遇到的16进制转字符串中文乱码问题及解决方案 在PHP开发中,有时候我们会遇到需要将16进制形式的数据转换为字符串的需求,但在这个过程中可能会出现中文乱码的问题。本文将介绍...
    99+
    2024-03-05
    php 字符串 进制
  • Golang解析JSON遇到的坑及解决方法
    目录写在前面空指针会被解析成字符串"null"int类型会被解析成float64写在前面 在写go的时候经常用到序列化、反序列化,记录一下遇到过的坑。 空指针会被...
    99+
    2023-02-26
    Golang解析JSON Go 解析JSON Go JSON
  • Vue-Luckysheet的使用方法及遇到问题解决方法
    Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。 配置文档 · API · 教程:快速上手 | Luckyshe...
    99+
    2022-11-13
    Vue Luckysheet使用 Vue Luckysheet
  • Java中HashMap与String字符串互转的问题解决
    目录背景:原因:背景: 当我们有需求将HashMap转为Json格式的String时,切记不要使用HashMap的toString()方法,需要使用FastJson/Gson将Has...
    99+
    2024-04-02
  • Java 画时钟遇到的问题及解决方法
    这期内容当中小编将会给大家带来有关Java 画时钟遇到的问题及解决方法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.不能一直得到当前的时间,导致刷新时间不变。刚开始我自以为把int s = calen...
    99+
    2023-06-25
  • MySQL无法存储Emoji表情问题的解决方法分析
    本文实例讲述了MySQL无法存储Emoji表情问题的解决方法。分享给大家供大家参考,具体如下: 数据插入的时候报错: 1366 - Incorrect string value: '\xF0\x9F\x98...
    99+
    2024-04-02
  • Python字符串的字符转换、字符串劈分、字符串合并问题怎么解决
    1.字符串的字符转换1.1.字符转换的概念在前面说的的字符串替换,是将字符串中的一个子串替换成了新的子串,如果我们想对字符串中的某些字符进行转换,也就是对字符串中的单个字符进行替换,可以调用方法maketrans和translate来实现。...
    99+
    2023-05-23
    Python
  • C#中常见的字符串操作问题及解决方法
    C#中常见的字符串操作问题及解决方法字符串拼接问题在C#中,我们经常需要将多个字符串拼接在一起,但是如果使用简单的加号"+"运算符,则会出现性能问题。这是因为在每次拼接字符串时,都会创建一个新的字符串对象,导致内存的频繁分配和回收。解决方法...
    99+
    2023-10-22
    解决方法 字符串操作问题
  • word遇到问题需要关闭的解决方法
    这篇文章主要介绍word遇到问题需要关闭的解决方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!  第一步,打开word(不是WORD文件而是桌面上或者开始-程序里的word快捷方式) 出现了一个提示,显示...
    99+
    2023-06-06
  • 安装vCenter6.0遇到的问题以及解决方法
    实验环境: 在Window Server 2008 R2上安装vCenter6.0,数据库采用的SQL Server2012   问题一: 安装到50%的时候提示:无法启动invsvc服务以及无法运行vdcpromo等各种问题,点...
    99+
    2023-06-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作