第3章:数据格式基础(上)——JSON结构解析、XML解析与生成、CSV文件读写、YAML配置管理

各位同学,欢迎来到数据格式基础的上半部分。说实话,在医疗设备这个行当里,数据格式就是咱们的通用语言。设备之间要对话,系统之间要传数据,全靠这些格式来搭桥。我做了十几年医疗软件,见过太多因为格式问题导致的故障——有的数据丢了,有的解析错了,最严重的一次差点影响病人数据上报。所以这一章,咱们得把基础打扎实。

3.1 JSON结构解析——轻量级的数据交换王者

JSON,全称JavaScript Object Notation。说白了,就是一种轻量级的数据交换格式。为什么医疗设备特别喜欢它?因为够简单、够直观、解析速度还快。

我个人习惯,在医疗设备的数据接口中,JSON用得最多。比如病人基本信息、设备状态上报、检查结果传输,这些场景JSON都能胜任。

核心要点:JSON由两种结构组成——对象(Object)和数组(Array)。对象用花括号{}包裹,数组用方括号[]包裹。

来看一个典型的医疗设备JSON数据示例:

{
  "deviceId": "DX-2024-001",
  "deviceName": "数字化X光机",
  "status": "online",
  "patientInfo": {
    "patientId": "P20240315001",
    "name": "张三",
    "age": 45,
    "gender": "male",
    "examType": "chest"
  },
  "measurements": [
    {
      "timestamp": "2024-03-15T10:30:00Z",
      "parameter": "kVp",
      "value": 120,
      "unit": "kV"
    },
    {
      "timestamp": "2024-03-15T10:30:01Z",
      "parameter": "mA",
      "value": 200,
      "unit": "mA"
    }
  ]
}

嗯,这里要注意几个关键点。第一,键名必须用双引号包裹。第二,字符串值也必须用双引号。第三,最后一个元素后面不能有逗号。我在项目中遇到过,有个同事在JSON末尾多写了个逗号,结果解析器直接报错,查了半天才发现。

我的小技巧:写JSON的时候,建议用在线校验工具先验证一遍。或者用代码里的JSON库来序列化,别手写。手写容易出错,尤其是嵌套层级多的时候。

解析JSON,在Python里用json模块就行。我一般这么写:

import json

# 从字符串解析
json_str = '{"deviceId": "DX-2024-001", "status": "online"}'
data = json.loads(json_str)
print(data["deviceId"])  # 输出: DX-2024-001

# 从文件读取
with open("device_data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# 生成JSON字符串
output = json.dumps(data, indent=2, ensure_ascii=False)
print(output)

你想想看,如果不用ensure_ascii=False,中文会被转成Unicode编码,可读性很差。我刚开始做医疗设备项目时就踩过这个坑,病人姓名显示成\u5f20\u4e09,被测试同事吐槽了好久。

3.2 XML解析与生成——老牌工业标准

XML,可扩展标记语言。虽然现在JSON很流行,但在医疗设备领域,XML依然占据重要地位。为什么?因为很多医疗设备标准协议,比如HL7、DICOM,底层都依赖XML。

XML的结构,说白了就是标签套标签。每个标签可以带属性,也可以有子标签。来看一个医疗设备配置的XML示例:

<?xml version="1.0" encoding="UTF-8"?>
<deviceConfiguration>
    <device id="DX-2024-001">
        <name>数字化X光机</name>
        <manufacturer>蓝海医疗</manufacturer>
        <parameters>
            <parameter name="kVp" unit="kV">
                <min>40</min>
                <max>150</max>
                <default>120</default>
            </parameter>
            <parameter name="mA" unit="mA">
                <min>10</min>
                <max>500</max>
                <default>200</default>
            </parameter>
        </parameters>
    </device>
</deviceConfiguration>

解析XML,Python里常用的有xml.etree.ElementTreelxml。我个人更推荐lxml,功能更强大,处理大文件也更快。

from lxml import etree

# 解析XML字符串
xml_str = '''<device><name>X光机</name></device>'''
root = etree.fromstring(xml_str)
print(root.find("name").text)  # 输出: X光机

# 从文件解析
tree = etree.parse("device_config.xml")
root = tree.getroot()

# 遍历所有参数
for param in root.findall(".//parameter"):
    name = param.get("name")
    default = param.find("default").text
    print(f"参数: {name}, 默认值: {default}")

# 生成XML
new_device = etree.Element("device")
etree.SubElement(new_device, "name").text = "CT扫描仪"
etree.SubElement(new_device, "status").text = "active"
xml_output = etree.tostring(new_device, pretty_print=True, encoding="UTF-8")
print(xml_output.decode())

避坑指南:我曾经在解析XML时,没注意命名空间(namespace),结果find方法一直返回None。查了半天才发现,标签前面有个ns:前缀。处理带命名空间的XML,要用{namespace}tag这种写法。

XML的优点是自描述性强,缺点是冗余信息多,文件体积大。在医疗设备中,我建议:配置文件和协议报文用XML,实时数据传输用JSON。

3.3 CSV文件读写——最朴素的表格数据

CSV,逗号分隔值。别看它简单,在医疗设备中用处可大了。比如导出检查记录、批量导入病人信息、设备日志分析,CSV都是首选。

CSV的格式,说白了就是一行一条记录,每列用逗号隔开。但要注意,如果字段里包含逗号或换行符,需要用双引号包裹。

来看一个病人检查记录的CSV示例:

病人ID,姓名,检查类型,检查日期,检查结果
P001,张三,胸部X光,2024-03-15,正常
P002,李四,腹部CT,2024-03-16,发现结节
P003,王五,心电图,2024-03-16,窦性心律

Python里读写CSV,用内置的csv模块就行。我一般这么写:

import csv

# 写入CSV文件
with open("exam_records.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["病人ID", "姓名", "检查类型", "检查日期", "检查结果"])
    writer.writerow(["P001", "张三", "胸部X光", "2024-03-15", "正常"])
    writer.writerow(["P002", "李四", "腹部CT", "2024-03-16", "发现结节"])

# 读取CSV文件
with open("exam_records.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"病人{row['姓名']}的检查结果是{row['检查结果']}")

我的经验:DictReaderDictWriter比普通reader更方便,可以直接用列名访问数据。另外,写入时一定要加newline="",否则Windows系统下会多出空行。这个坑我踩过不止一次。

CSV的优点是简单、通用,任何表格软件都能打开。缺点是缺乏数据类型定义,所有字段都是字符串。所以在读取后,记得做类型转换。

3.4 YAML配置管理——人类友好的配置文件

YAML,YAML Ain't Markup Language。这个名字挺有意思,递归缩写。YAML的设计目标就是——人类可读性第一。

在医疗设备中,YAML特别适合做配置文件。比如设备参数配置、系统设置、环境变量。为什么?因为YAML支持注释,结构清晰,还支持复杂的数据类型。

来看一个医疗设备系统的YAML配置示例:

# 医疗设备系统配置文件
system:
  name: "蓝海医疗影像系统"
  version: "3.2.1"
  log_level: "INFO"

database:
  host: "192.168.1.100"
  port: 3306
  name: "medical_db"
  user: "admin"
  password: "${DB_PASSWORD}"  # 使用环境变量

device:
  - id: "DX-001"
    type: "X光机"
    ip: "192.168.1.10"
    port: 8080
    enabled: true
  - id: "CT-001"
    type: "CT扫描仪"
    ip: "192.168.1.11"
    port: 8081
    enabled: false

alerts:
  email:
    enabled: true
    recipients:
      - "admin@example.com"
      - "tech@example.com"
  sms:
    enabled: false

解析YAML,Python里用PyYAML库。安装命令:pip install pyyaml

import yaml

# 读取YAML文件
with open("config.yaml", "r", encoding="utf-8") as f:
    config = yaml.safe_load(f)

print(config["system"]["name"])  # 输出: 蓝海医疗影像系统
print(config["device"][0]["type"])  # 输出: X光机

# 写入YAML文件
config["system"]["version"] = "3.3.0"
with open("config.yaml", "w", encoding="utf-8") as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)

避坑指南:YAML对缩进非常敏感,必须用空格,不能用Tab。我曾经在项目中,因为编辑器自动把空格转成了Tab,结果YAML解析一直报错。建议在编辑器里设置显示空白字符,一眼就能看出问题。

另外,YAML里布尔值的写法要注意。true、True、TRUE、yes、on都会被解析为布尔值True。如果你想要字符串"true",记得加引号。

3.5 四种格式的对比与选择

好了,四种格式都讲完了。咱们来做个对比,方便你在实际项目中做选择。

特性 JSON XML CSV YAML
可读性 非常高
解析速度 非常快
文件大小 最小
支持注释
数据类型 丰富 丰富
适用场景 API数据交换 标准协议、文档 表格数据导出 配置文件

我个人建议:

  • 实时数据传输:用JSON,解析快、体积小
  • 遵循医疗标准协议:用XML,比如HL7、DICOM
  • 批量数据导出导入:用CSV,通用性强
  • 系统配置文件:用YAML,可读性好、支持注释

核心总结:没有最好的格式,只有最合适的场景。在医疗设备开发中,往往是多种格式混合使用。关键是理解每种格式的特点,知道什么时候该用哪个。

好了,这一章的内容就到这儿。下一章咱们继续讲数据格式的下半部分,包括二进制数据、Protocol Buffers、MessagePack这些更高级的格式。到时候再聊!