从json中提取数据并将其转换为CSV
项目描述
jsonToCsv
通过元语言(格式字符串)将json数据转换为csv
默认情况下,输出csv符合RFC 4180规范(行为可以通过选项进行更改)。
问题
将json转换为csv的问题在于,json是一个动态的、多类型的、嵌套的格式。另一方面,csv是一个固定格式的单类型格式。
JsonToCsv通过定义一个元语言(格式字符串)来解决此问题,该元语言可用于定义可重复和固定格式的步骤,从而将广泛的json域空间扁平化为瘦的csv空间。
格式字符串
由于csv是固定格式的字段,而json是自由格式的,因此必须开发一个元语言来描述各种移动以找到并输出值到固定格式。本节描述了该格式。
格式str
格式str是一系列操作和键,以及零个或多个“行项”。
键
格式字符串中列出的每个键名都用双引号引起来。
如果键以操作符开头,它用于获取一个值。
如果键没有以操作符开头,它将成为要打印的值。
- 除非您使用操作符来更改级别,否则引号的键后面应该跟一个逗号来分隔。
。
键可以位于行项之前、之后或其中,并且键将按出现的顺序输出。
示例
“hostname” # 在当前级别打印键hostname
.”hostname”[ # 在“hostname”键上应用.(映射访问)操作符
“hostname”, “cheese” # 当前级别的两个键
行项
“行项”是迭代以生成csv每一行的键。
行项由键前的“+”符号给出。
您可能有多个行项(因此迭代多个键),并且您将得到
每个找到的最内层行项的输出行。
您不能关闭行项然后尝试在另一级别打开另一个行项。
如果您没有定义行项(例如单个记录),将生成一个csv行。
示例
- +”instances”[ # 对于当前级别由键给定的数组中的每个项目
# “instances”,我们将生成一个csv行。
.”Something”[ # 进入根中名为“Something”的键 +”Data”[ # 在“Data”中找到的每个数组元素上迭代 +”instances” # 在每个“Data”中找到的每个“instances”数组元素上再次迭代
映射访问
“映射访问”操作符意味着在当前级别访问一个键
并将“当前级别”推进到包括这个键访问。
映射访问由键前的“.”操作符给出
示例
.”Data”[ # 通过键“Data”下降“当前级别”
列表-映射访问
- “列表-映射访问”操作符意味着在当前级别下搜索一个映射列表,
在给定的键下找到,直到该映射中的键与给定的值匹配。
您在键前使用“/”操作符前缀,并在方括号内定义一个比较操作。
- 它将停止在找到的第一个匹配项上。不支持重复,因为这会创建
任意数量的字段(而csv是固定字段)
例如,如果您有一个“attributes”键,它包含多个映射,例如{"key" : … , "value" : … }
并且您想选择“key” == “color”的映射,它将如下所示
/”attributes”[“key”=”color”
在级别之间移动
您会注意到每个操作都会下降一个级别,表示它后面跟着一个方括号,“[”。
如果您想回到上一个级别,只需关闭方括号“]”。
在格式字符串结束时,必须关闭所有打开的方括号。
空白字符
空格和换行符通常被忽略,并且可以使用它们来使东西看起来更美观。
注释
您可以通过使用哈希[‘#’]字符直接在格式字符串中进行注释。
从哈希字符到行尾的所有内容都将被忽略。
这对于与多行模式结合使用以说明每一行正在做什么非常有用。
请参阅“带有内联注释的示例”部分以获取示例。
逗号
逗号应用于分隔同一级别的项目,因此打印引号键之后,如果在上一个级别上还有更多项目,则紧接在关闭括号“]”之后。
顺序
键按在格式字符串中从左到右找到的顺序打印。
- 您可以进入级别,然后返回,打印键,然后像您喜欢的次数一样返回到这些级别。
。
空值
如果json映射中的值是“null”或未定义的,
则给值提供一个空字符串(默认情况下,可以将其更改为任何字符串)。
如果在格式字符串后跟一个键(例如缺少键或类型错误)出现错误,
您可以通过传递‘–debug’标志来在stderr上打印每次为什么返回null的原因。
区分大小写
所有键都是区分大小写的。
多行
由于非引号空白被忽略,您可以使用换行符、空格和制表符使长模式更易于阅读。
工具
此模块包含一个名为jsonToCsv的脚本,可以独立使用来执行这些操作。
用法:jsonToCsv [格式字符串]
根据提供的格式字符串将json字符串(通过stdin提供)格式化为csv。
选项
- --null-value=XXX
使用“XXX”而不是空字符串作为null值
—quote-fields=X 默认为“智能引号”,即根据RFC 4180按需引号。您可以在此处明确指定“true”或“false”以强制行为。
—help 显示此信息
--format-help
显示格式字符串表示的用法
- --version 打印版本
cat myFile.json | jsonToCsv ‘+”Results”[“name”, “org”]’
模块
示例
主要公共模块是json_to_csv.JsonToCsv。
构造函数只需要格式字符串[formatStr](一种用于定义提取模式的简单特定元语言的字符串)。
然而,您可以选择定义一个替代值来表示不可达或定义为null的字段[nullValue]。
模块 PyDoc
您可以在以下位置访问pydoc:http://htmlpreview.github.io/?https://github.com/kata198/jsonToCsv/blob/master/doc/index.html
模块使用示例
请参阅:https://github.com/kata198/jsonToCsv/blob/master/example.py 和 https://github.com/kata198/jsonToCsv/blob/master/example_mutli.py。
对于使用模块直接提取并重新格式化为各种格式(CSV、TSV、文本表)的基本示例
请参阅:https://github.com/kata198/jsonToCsv/blob/master/example.py 和 https://github.com/kata198/jsonToCsv/blob/master/example_mutli.py。
对于使用模块直接提取并重新格式化为各种格式(CSV、TSV、文本表)的基本示例
提取数据
一旦您编写了formatStr并创建了JsonToCsv对象,您就可以开始解析了!
extractData
extractData是JsonToCsv的“核心”方法。它执行实际的从json到格式字符串的解析,创建一系列行。
此方法的输出是一个列表的列表,外层列表是每一行,每一行是一个列表,其中每个元素代表一个字段。
需要“extractData”的一些更复杂的使用场景包括
创建输出格式的替代格式(如TSV或文本表,或插入到GUI中)
数据分析,即过滤或修改
连接来自多个JSON条目的数据(有关更多信息,请参阅该部分)
您需要做的任何事情
您可以将此函数的输出传递给“dataToStr”方法以将其转换为可打印的字符串。
dataToStr
dataToStr提供了将数据(来自extractData)转换为可打印字符串的途径。
第一个参数是extractData提供的列表的列表
它还以下列可选参数
separator - 默认为逗号,可以使用制表符作为TSV,或您想要的任何内容
lineSeparator - 默认为CRLF(\r\n),这是RFC4180标准,但您可以使用其他内容(如\n)。
quoteFields - 您可以将此设置为True或False以根据RFC4180标准显式引号或不引号数据。默认为字符串“智能”,这意味着数据将被扫描以查看是否需要引号,如果是这样,它将引号数据。否则,它不会。通常您会希望保持默认设置。
convertToCsv
最基本和直接的方法是“convertToCsv”函数。您可以传递一个字符串(原始数据)或一个字典(例如由‘json’模块解析),并且您将输出CSV行,准备好传递给“print”函数。
这与调用extractData并将其传递给dataToStr相同,除了您只能通过此函数使用逗号作为分隔符。
此函数接受与上面“dataToStr”中描述的“lineSeparator”和“quoteFields”相同的参数。
findDuplicates
此函数可以帮助您识别多条记录中同一字段包含相同数据的情况。
您传入由 extractData 提取的数据,选择一个以0为起始的“fieldNum”,这将决定对每行数据检查哪个字段以查找重复值。
如果“flat”参数为False(默认值),输出是一个映射,其键是所有有重复条目的字段值。
如果“flat”为True,输出仅是一个字段值列表的列表。基本上,是来自extractData的数据,但只包括在所选字段中有重复的数据。
joinCsv
joinCsv将接受两个列表的列表(即“extractData”返回的),以及两个0起始数字,joinFieldNum1(第一个数据集中“连接字段”的索引)和joinFieldNum2。
例如,您可能有两组数据,都描述了人。“社会保险号码”可能是其中一个数据集从零开始的第4个字段,另一个数据集的第0个字段。因此,如果您想合并这两个数据集,可以使用此方法,通过连接这些字段(即两个joinFieldNum列之间的字段匹配实例,该索引从第二个数据集中删除,并将第二个数据集附加到第一个数据集上)。
multiJoinCsv
与joinCsv相同,但joinCsv在数据集内部不允许有重复项。因此,对于上面的数据,假设同一社会保险号码在一个数据集中有两个人名……那么哪个是对的?计算机无法确定。
因此,此函数将尽最大努力,在上述示例中,您将得到与该社会保险号码相关联的人X的数据集。因此,如果您在csvData1和csvData2中都有重复的字段,您将最终得到4条记录
A1 B1
A2 B1
A1 B2
A2 B3
这会非常积极地匹配,但您可能会开始得到一些无效数据。
完整示例
。“数据”[ +“实例”[ “hostname”, /“属性”[“key”=“role” “value”], /“属性”[“key”=“created_at” “value”, “who_set”], 。 “性能”[ “cpus”, “memory” ] ] ]
说明
给定的json对象将首先通过“数据”键递归下降,其中期望一个映射。
在这个映射中,“实例”将是“行项”,即我们将遍历“实例”列表中的每个项来生成每行csv。
所以,对于“实例”中的每个映射
我们打印“hostname”键作为第一csv元素
我们进入键“属性”下的映射列表
搜索其中一个映射有“key”值为“role”的条目,并打印该映射“value”键的值作为第二个csv元素。
然后,我们返回到上一级。
然后我们再次进入该键“属性”下的映射列表
搜索其中一个映射有“key”值为“created_at”的条目,并打印该映射“value”键的值作为第三个csv元素。
然后,我们打印该映射的“who_set”键的值作为第四个csv元素。
然后,我们返回到上一级
然后我们进入键“性能”下的映射
我们打印此级别“cpus”键的值作为第五个csv元素。
我们打印此级别“memory”键的值作为第六个csv元素。
然后,我们返回到上一级
然后,我们返回到上一级
(我们在此处完成迭代)
然后,我们返回到上一级
带有内联注释的示例
以下是要解析的以下json:https://github.com/kata198/jsonToCsv/blob/master/example_multi.json
PARSE_STR = ''
“日期”, # 每行的第一个元素将是顶层“日期”的值
#
+“结果”[ # 遍历“结果”下的每个列表成员
“myBeforeKey”, # 将“myBeforeKey”作为每行中的下一个项包含
+“实例”[ # 遍历“实例”下的每个列表成员
“主机名”,# 在每行“实例”下包含“主机名”
“ip”,# 下一个要添加的键是“ip”
/“属性”[{“名称”=“状态” # 下降到“属性”下的列表-映射中并查找
# 键“名称”具有“状态”值的条目
“值”,# 在匹配的映射中打印键“值”的值
], # 离开此匹配的映射,返回上一级
。“puppet_data”,# 下降到“puppet_data”键找到的映射
“主机组”,# 打印此级别的“主机组”键
], # 返回上一级
/“属性”[{“名称”=“域” # 下降到“属性”下的列表-映射中并查找
# 键“名称”具有“域”值的条目
“值”,# 打印此匹配映射中的“值”键
], # 回到上一级
/“属性”[{“名称”=“所有者” # 下降到“属性”下的列表-映射中并查找
# 键“名称”具有“所有者”值的条目
“值”,# 打印此级别的键“值”
] # 回到上一级
] # 回到上一级
“myAfterKey”,# 将键“myAfterKey”的值附加到所有之前的行
], # 返回上一级
“name”,# 将键“name”的值附加到所有之前的行
‘’’