详细介绍一下Python如何对JSON格式数据进行处理?

在Python中对于JSON数据的处理是在日常开发中的常见需求之一。通常情况下,对JSON数据的处理主要涉及到如下的的几个步骤

  • 对于JSON数据的解析操作
  • 对于JSON数据的处理操作
  • 对于JSON数据的格式转换操作

在Python中我们可以通过json 这个标准库来实现对于JSON数据的上述操作,下面我们就来详细介绍一下如何在Python中通过json库来处理JSON数据。

想要所使用json库,首先需要导入json处理模块,由于它是属于Python语言内置的JSON数据处理的标准库,所以在使用的时候不需要安装直接进行导入就可以了,如下所示。

导入模块库之后,接下来我们就来看看如何将JSON字符串转换成Python对象,例如可以将JSON字符串转换成字典或者是列表的形式。如下所示,我们可以通过json.loads()方法,来从字符串中加载JSON数据。

这种情况下,我们可以将这个字符串转换成一个字典对象。

当然除了从字符串中获取JSON数据之外,我们还可以通过json.load()的方法从一个JSON文件中获取到文件内容并且将其加载为一个Python对象,如下所示。假设我们有一个data.json的JSON文件,内容如下。

接下来,我们就可以通过json.loads()的方法从文件中加载到JSON数据并且将其转换为一个Python对象。如下所示。

通过上面的方式,我们可以将JSON数据转换成了一个Python的对象,这里需要注意JSON对象会被转换为字典,JSON数组对象会被转换为列表,其内部元素会被转换为字典。有了这样的转换之后,我们就可以像是操作普通操作对象一样的方式来操作这个转换之后的Python对象。

介绍完成如何将JSON数据加载为Python对象的方式之后,接下来我们来看看如何将Python对象转换为JSON格式的字符串。

一般情况下,我们可以通过json.dumps()方法将Python对象转换为JSON字符串,如下所示,我们先定义了一个字典,然后通过json.dumps()方法转换成字符串。

根据上面的方法,我们既然可以从JSON格式数据中读取到JSON数据来进行Python对象的转换操作,那么我们就可以通过json.dump()方法将Python对象转换为JSON字符串将其写入到文件中,如下所示。

在将Python对象转换为JSON字符串的时候,json.dump()方法还提供了一些额外的参数进行JSON输出格式的修改,如下所示。

  • indent:通过这个参数,我们可以来设置缩进的级别用来美化输出格式。
  • sort_keys:通过这个参数,我们可以设置对象Key可以按照字典排序。
  • separators:通过这个参数,我们可以指定分隔符,因为在默认情况下是(\”, \”, \”: \”),我们也可以根据自己的需求来进行动态调整。

如下所示,我们可以通过参数设置来美化JSON输出。

根据Key按照字典进行排序。

在实际开发过程中,可能由于系统之间的对接问题导致JSON数据格式不符合标准的处理格式,这样在通过json模块进行JSON数据处理的时候,就会抛出JSONDecodeError异常,这个时候就需要我们通过Python的异常处理机制来捕获并且处理这些异常,如下所示。

通过异常处理机制,可以使得我们的应用程序更加健壮。

在实际开发中,除了对于JSON数据最为基础的解析以及序列化操作之外,在json模块中还提供了一些高级的处理功能,下面我们就来介绍一下Python中一些常用的JSON高级处理方案。

在实际开发中,我们可能会因为业务需求将Python对象转换为JSON数据,或者是将JSON数据转换为Python对象,有些需求可能需要我们通过自定义的方式来实现这个转换操作,这个时候,我们就需要来继承json.JSONEncoder和json.JSONDecoder类来实现自定义的JSON数据转换逻辑。

如下所示,我们可以通过继承json.JSONEncoder来实现一个自定义的Python对象转换JSON数据的编码器,在进行相关处理逻辑的时候,可以通过这个编码器来实现自定义编码操作。

在上面的实现中,我们自定义了一个日期对象的编码器,在处理日期对象的时候,可以通过这个编码器来进行指定格式的日志编码。

同样的,我们可以继承json.JSONDecoder来实现就日期的解码器,将复杂日期格式转换为我们需要的Python对象的数据格式,如下所示,将字符串解析为datetime对象。

这样我们就完成了自定义日期类型的转换。

根据上面的实现步骤,在Python中对于JSON格式数据的处理主要涉及到三个方面的内容,对于JSON数据的解析、对于JSON数据的反解析、对于JSON数据的实际处理。在上面的介绍中,我们展示了最为基础的JSON数据格式处理方式。当然在实际处理中,还有很多高级用法,有兴趣的读者可以关注博主,学习更多Python相关的内容。

什么是JSON?怎么用Python来编码+解码JSON对象?

本章节我们将为大家介绍如何使用 Python 语言来编码和解码 JSON 对象。

json处理模块的主要任务,是将一个JSON对象,转换成Python数据类型数据进行处理,或者反之,将Python数据类型数据,转换成JSON对象(字符串流),在不同的模块或者系统间传输。

  • 对象表示为键值对
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

上面就是一个JSON格式数据。它开起来就像是在Python中的字典数据类型。我们可以通过json模块将它转换成字符串或者反过来将字符串转换成字典数据类型。

JSON也支持各种数据类型,它的数据类型和Python各种数据类型之间的对比如下:

  • object —— dict
  • array —— list
  • string —— str
  • number —— int/float
  • true/false —— True/False
  • null —— None

在json模块中,用于处理json的主要是四个函数,分别是:

  • loads():从JSON字符串中读取数据并转换成Python数据类型
  • load():从JSON文件中读取数据并转换成Python数据类型
  • dumps():将Python数据类型数据转换成JSON字符串
  • dump():将Python数据类型数据转换成JSON字符串写入到文件
  • 从JSON数据转换到Python数据,叫反系列化(deserialization)
  • 从Python数据转换到JSON数据,叫系列化(serialization)

系列化:将Python数据转换成JSON字符串的方法。

下面我们先来看一个简单的例子。

上面的例子中,虽然看起来数据没有发生变化,但其实它们的数据类型已经发生了本质的改变:将字典数据类型的data,转换成了str类型,然后我们就可以将这个str类型的数据转换成流,在网络上进行传输或者写入到文件等。

将data写入txt文件中

这样就将data写入了students.txt,看看是不是已经将数据写进去了。

从JSON数据转换到Python类型数据,叫反系列化。可以通过loads()/load()这两个方法来完成。

  • parse_int参数

默认值为None,如果指定了parse_int,用来对JSON int字符串进行解码,这可以用于为JSON整数使用另一种数据类型或解析器。

parse_int参数,这里我们简单将其指定为float类型。

可以看到,age原来是整数类型,通过parse_int已经被转换成了float类型。

  • object_hook

默认值为None,object_hook是一个可选函数,此功能可用于实现自定义解码器。指定一个函数,该函数负责把反序列化后的基本类型对象转换成自定义类型的对象。

到这里就结束了,如果对你有帮助,欢迎点赞关注评论,你的点赞对我很重要

作者:北山啦

原文链接:https://blog.csdn.net/qq_45176548/article/details/115119022

数仓的两种轻量级数据交换格式:json与jsonb

本文分享自华为云社区《》,作者:yd_283975606。

  • 适用版本:【8.1.1(及以上)】

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于将数据从服务器发送到Web应用程序。它采用人类易读和机器易解析的文本格式,基于键值对的集合,用于表示结构。

json演进历程

参考DWS产品文档,JSON数据类型可以用来存储JSON(JavaScript Object Notation)数据。

可以是单独的一个标量,也可以是一个数组,也可以是一个键值对象,其中数组和对象可以统称容器(container):

  • 标量(scalar):单一的数字、bool、string、null都可以叫做标量。
  • 数组(array):[]结构,里面存放的元素可以是任意类型的JSON,并且不要求数组内所有元素都是同一类型。
  • 对象(object):{}结构,存储key:value的键值对,其键只能是用“”包裹起来的字符串,值可以是任意类型的JSON,对于重复的键,按最后一个键值对为准。

存储方式

json是输入字符串的完整拷贝,使用时再去解析,所以它会保留输入的空格,重复键以及顺序等;

jsonb解析后存储,删除语义无关的细节和重复的键,对键值也会进行排序,使用时不用再次解析。

性能差别

json由于精确拷贝,因此插入时性能较好,但是其在处理函数时,必须在每个执行上重新解析,因此其查询性能一般;

jsonb 数据以分解的二进制格式存储, 这使得它由于添加了转换机制而在输入上稍微慢些。但是其由于插入后即默认有序排列,因此可以更好地支持的额外操作(如bool关系的比较,顶层元素存在的判断)。并且,其在处理函数时, 不需要重新解析,查询性能较好。同时,jsonb支持创建btree、gist和gin索引。

1.标量(scalar):输入为数字、布尔类型时,使用单引号 ’ \’声明,输入为字符串时必须加 \” \”声明

2.数组(array):使用中括号[]包裹,满足数组书写条件。数组内元素类型可以是任意合法的JSON,且不要求类型一致。

3.对象(object):使用大括号{}包裹,键必须是满足JSON字符串规则的字符串,值可以是任意合法的JSON。

4.嵌套数组和对象:数组array中可以是任意合法的json元素,对象object则严格遵循了key:value的格式,两者结合可以方便地有序查找json值。

当前DWS支持创建列存json、jsonb。

1.jsonb_object_field(jsonb, text)

描述:输入的json类型为json-object,返回指定键对应的值(可能为json-object或json-array)

对应操作符:->

返回类型:jsonb

2.jsonb_array_element(array-jsonb, integer)

描述:输入的json类型为json-array,返回数组中指定下标的元素(为任意合法的JSON)

对应操作符:->

返回类型:jsonb

3.jsonb_extract_path((jsonb, VARIADIC text[])

描述:输入为json-object或json-array,返回$2所指路径的值。$2中可以为json-object对应的键值(字符串类型),也可以为json-array对应的下标(整数类型)

对应操作符:#>

注意:GaussDB(DWS)对象标识符支持以符号\”#“结尾,为避免a#>b解析过程出现歧义,因此操作符”#>\”前后需要增加空格,否则解析报错。

返回类型:jsonb

1.jsonb会丢弃空格等语义无关的细节

2.jsonb会默认对输入键值的重新排序

比较规则如下:

首先比较类型:object-jsonb > array-jsonb > bool-jsonb > num-jsonb > str-jsonb > null-jsonb

同类型则比较内容

  • str-json类型:依据text比较的方法,使用数据库默认排序规则进行比较,返回值正数代表大于,负数代表小于,0表示相等。
  • num-json类型:数值比较
  • bool-json类型:true > false
  • array-jsonb类型:长度长的 > 长度短的,长度相等则依次比较每个元素。
  • object-jsonb类型:长度长的 > 长度短的,长度相等则依次比较每个键值对,先比较键,再比较值。

目前,DWS的JSON/JSONB的功能基本完善。主要体现在函数、操作符、索引功能的支持。但目前来说,JSON列存仍然采用的是直接存储JSON数据,即将原始的JSON数据存成单独的一列,以完整的JSON值作为最小的粒度在磁盘上,具体如下:

优点是:JSON则天然支持Schema Evoluation,上游业务的变更,只需要在JSON列数据中进行增删相应的字段,无需对数仓中的表做任何DDL就能完成,也能对中间的ETL作业做到透明,最大程度地保留了半结构化数据的易用性和灵活性,能大大降低维护和管理表结构的成本。

缺点是:应用端查询时需要选择合适的处理函数和方法,才能解析到需要的数据,开发较为复杂,如果JSON较复杂,同时查询性能会有退化,因为每次JSON列的数据参与计算的时候,都需要对JSON数据完整的解析一遍,比如需要抽取出整个JSON中某个字段,那么查询引擎执行的时候就要读出每一行JSON,解析一遍,取出需要的字段再返回。这中间会涉及大量的IO和计算,而需要的可能只是JSON数据成百上千字段当中的一个字段,这中间的大量IO和计算都是浪费的。

另外,当前云原生分支上JSON的向量化支持仍然是沿用的通用的向量化框架,没有定制化的向量化函数。通用的向量化函数框架本质上来说仍然为行存的调用,并不是完全意义上的向量化。

如上所述,后续想要提升JSON/JSONB的查询性能,首先必须提升JSON的存储方式,即在解析前端将JSON拍平成宽表,真正意义上发挥JSON半结构化数据的优势。

这种做法的优点是:写入DWS时,因为是普通列写入,所以写入性能会更好,同时在查询侧,不需要对JSON数据进行解析,查询性能也会更好。

缺点是:每当上游的数据格式有变更时,比如变更数据类型、增删字段、执行DDL进行加列或者删列,中间的实时数据ETL作业也需要进行适配改动并重新上线,使用非常不灵活,也会额外增加运维和开发负担。并且当JSON的每一个键值都为一列,若出现异常数据,可能导致列数的急速膨胀,进而影响性能。

当前Hologres的方案类似,但其对特殊的列采用单独列(属性为JSON)存储那些同质化不强的json键值(极少数出现的json键值)

另外,当前列存JSON的性能当前瓶颈点在于向量化的性能,一方面需要提升通用当前DWS的向量化能力,另一方面也可以考虑对json函数做出优化。

关注 点击下方,第一时间了解华为云新鲜技术~

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。