dsh-jsonl-stream
v0.1.0
Published
JSONL/NDJSON stream plugin for DeepSeek Harness: parse line-delimited JSON with bad-line tolerance, sample records (head/tail/random/evenly) with reproducible seeds, and project nested fields via dot paths. Zero runtime dependencies, read-only.
Maintainers
Readme
dsh-jsonl-stream
DeepSeek Harness 的 JSONL / NDJSON 处理工具箱:parse_jsonl 逐行解析并容错报告坏行,sample_jsonl 按头/尾/随机/均匀四种方式抽样,project_fields 用点号路径抽取嵌套字段。三者面向大文件设计,支持大小与行数上限、确定性随机种子。只读、零运行时依赖。
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-jsonl-stream
- npm:https://www.npmjs.com/package/dsh-jsonl-stream
功能说明
JSONL(每行一个 JSON,又称 NDJSON)是日志、导出数据与模型训练集的常见格式,但它有个麻烦:文件常常几十万行,用普通 JSON 工具读会炸,用文本工具看又看不出结构。本插件把它拆成三个动作——看质量、看内容、看字段。
parse_jsonl —— 数据质量体检
逐行 JSON.parse,坏行不中断,给出总行数、空行数、有效记录数、无效行明细(行号 + 原因 + 原文):
来源:C:\data\events.jsonl
总行数:6(空行 1)
有效记录:4
无效行:1
无效行明细:
第 5 行 Expected ',' or '}' after property value in JSON at position 29
{"ts":"2026-09-27T09:00:06Z" level:"info"}
记录预览(前 2 条):
1 {"ts":"2026-09-27T09:00:00Z","level":"info","msg":"start"}
2 {"ts":"2026-09-27T09:00:03Z","level":"warn","msg":"slow query"}
… 其余 2 条略sample_jsonl —— 抽样看内容
四种抽样方式,其中 random 支持固定种子,同样的 seed 永远得到同样的样本,便于在对话里复现结论:
模式:random(seed=7)
有效记录:4,抽样 2 条
(已跳过 1 个无效行)
1 {"ts":"2026-09-27T09:00:00Z","level":"info","msg":"start"}
6 {"ts":"2026-09-27T09:00:09Z","level":"info","msg":"done"}project_fields —— 字段投影看结构
用点号路径抽取字段,支持嵌套对象与数组下标(user.name、items.0.id),缺失字段用占位符标出,一眼看出哪些记录结构不一致:
字段:ts, level, user.name
有效记录:4,输出 4 条
(已跳过 1 个无效行)
行 ts | level | user.name
1 2026-09-27T09:00:00Z | info | alice
2 2026-09-27T09:00:03Z | warn | -
4 2026-09-27T09:00:05Z | error | bob
6 2026-09-27T09:00:09Z | info | -也支持 format=json 直接输出 JSON 数组,便于二次处理。
安装
npm install dsh-jsonl-stream安装后在 cordis.patch.yml 中加入:
- insert:
- id: jsonl-stream
name: "dsh-jsonl-stream"使用说明
三个工具都支持 path(文件路径)或 text(内联文本)二选一,text 优先。
parse_jsonl
| 参数 | 类型 | 说明 |
|---|---|---|
| path | string | JSONL 文件路径 |
| text | string | 内联 JSONL 文本(优先于 path) |
| max_lines | number | 最多解析行数,默认 1000,上限 100000 |
| preview | number | 预览记录条数,默认 5,上限 50 |
| strict | boolean | true 时遇到第一个坏行立即报错(默认 false,容错跳过) |
| max_size | number | 文件大小上限(KB),默认 10240,上限 102400 |
用户:这个 jsonl 文件能不能用,有没有坏行
parse_jsonl(path="data/events.jsonl", preview=3)用户:我要严格校验,有一条坏行就停下来
parse_jsonl(path="train.jsonl", strict=true)sample_jsonl
| 参数 | 类型 | 说明 |
|---|---|---|
| path / text | string | 同上 |
| count | number | 抽样条数,默认 5,上限 200 |
| mode | string | head(默认)| tail | random | evenly |
| seed | number | random 模式的随机种子,默认 42 |
| max_lines | number | 最多解析行数,默认 1000,上限 100000 |
| max_size | number | 文件大小上限(KB),默认 10240,上限 102400 |
用户:看看这个日志文件最后几条
sample_jsonl(path="app.log.jsonl", count=5, mode="tail")用户:均匀采样 10 条看看整体分布
sample_jsonl(path="corpus.jsonl", count=10, mode="evenly")project_fields
| 参数 | 类型 | 说明 |
|---|---|---|
| path / text | string | 同上 |
| fields | string | 要抽取的字段路径,逗号分隔,如 id,name,meta.tags(必填,最多 50 个) |
| format | string | lines(默认,表格化)| json(JSON 数组) |
| missing | string | 字段缺失时的占位符,默认 - |
| limit | number | 最多输出条数,默认 20,上限 200 |
| max_lines | number | 最多解析行数,默认 1000,上限 100000 |
| max_size | number | 文件大小上限(KB),默认 10240,上限 102400 |
用户:把每条记录的 id 和用户名字列出来
project_fields(path="rows.jsonl", fields="id,user.name,user.email")用户:我要把结果接到下一步处理
project_fields(path="rows.jsonl", fields="id,score", format="json")典型场景
- 数据交付前体检:拿到一份 JSONL 数据集先跑
parse_jsonl,确认坏行数量与位置再决定是否入库。 - 大文件定位坏行:
parse_jsonl直接给出坏行行号与原始文本,不用手动二分查找。 - 日志排查:
sample_jsonl(mode="tail")看最新若干条,mode="random"看整体形态。 - 字段一致性检查:
project_fields输出里出现的-就是结构性缺失,比逐条肉眼核对快得多。 - 构造测试样本:用固定
seed的随机抽样,保证每次拿到同一批数据,便于复现问题。 - 训练集抽样预览:
mode="evenly"覆盖整个文件,避免只看开头被前几条带偏。
安全边界
- 只读:三个工具都不写入、不修改、不删除文件,仅做读取与解析;测试含只读性断言(对比文件大小与 mtime)。
- 不访问网络:全部解析在本地完成,无任何外部请求。
- 不执行输入:只调用
JSON.parse做数据解析,不 eval、不加载模块、不解释输入内容。 - 二进制拒绝:读取时检测 NUL 字节,疑似二进制文件直接拒绝解析并报错。
- 大小与行数双重上限:
max_size上限 102400 KB、max_lines上限 100000;超限文件直接拒绝或按行数截断并在输出中显式提示。 - 字段路径防护:路径最多 10 级、字段最多 50 个,避免畸形输入引发超长遍历;越界数组下标返回缺失而非报错。
- 不收集敏感值:解析结果原样输出,不做脱敏。若文件含密钥等敏感信息,请改用
dsh-credential-scan先做泄露检查。 - 大文件提示:超大文件按
max_lines截断处理,截断时输出会带⚠提示,避免把部分结果误当全量。
其他插件集成说明
| 协作插件 | 集成方式 |
|---|---|
| dsh-credential-scan | 先用 credential-scan 确认 JSONL 中无凭据泄露,再用 jsonl-stream 解析内容 |
| dsh-table-render | 把 project_fields 的表格化输出交给 table-render 渲染成对齐表格进周报 |
| dsh-text-stats | 对 JSONL 原文做词频与体量统计,与 jsonl-stream 的记录级统计互补 |
| dsh-file-search | 先用 file-search 定位含关键词的行号,再用 sample_jsonl 查看上下文 |
| dsh-json-yaml-toolkit | 单条记录需要格式化或格式转换时,把该条交给 json-yaml-toolkit 处理 |
| dsh-log-parse | 日志类 JSONL 可在解析后用 log-parse 做级别分布与时间线分析 |
| dsh-fs-inspector | 解析前用 fs-inspector 查看文件体量,据此设置合适的 max_lines |
版本说明
- 0.1.0(2026-09-27):初始版本。
parse_jsonl:逐行解析 + 坏行容错 + 行号/原因/原文明细 + 记录预览 + strict 严格模式sample_jsonl:head / tail / random / evenly 四种抽样,随机模式支持可复现种子project_fields:点号路径字段抽取(支持数组下标)、表格化或 JSON 输出、缺失占位符- 二进制拒绝、大小与行数上限、字段路径深度与数量防护
RoadMap
v0.2(计划)
validate_jsonl:按 JSON Schema 子集逐行校验,输出不符合的记录convert_jsonl:JSONL ⇄ JSON 数组 ⇄ CSV 双向转换split_jsonl:按行数或体积切分为多个文件project_fields支持rename(字段别名)与default(缺失回填值)
v0.3(展望)
- 流式解析:按块读取,突破
max_lines限制处理超大文件 stats_jsonl:字段级统计(每个键的出现频率、类型分布、数值范围)- 支持 JSON Lines 之外的 JSON Text Sequences(RFC 7464,以 RS 分隔)
- 压缩文件直读(
.jsonl.gz),内部解压后流式解析
FAQ
Q:JSONL 和普通 JSON 有什么区别?
JSONL 每一行是一个独立的 JSON 值,行与行之间无逗号、无外层数组包裹。它适合流式追加与按行处理,代价是不能整体 JSON.parse。
Q:为什么我的文件第一行就报错?
常见原因是文件带了 UTF-8 BOM 或外层是 JSON 数组而非逐行 JSON。本插件不剥离 BOM,如果是数组格式(形如 [{...},{...}]),请用 dsh-json-yaml-toolkit 处理。
Q:totalLines 为什么和我 wc -l 的结果不同?
本插件的 totalLines 不把「文件末尾的换行符」算作额外一行。如果你的文件末尾没有换行,两个数字会一致。
Q:random 模式真的可复现吗?
是。使用固定种子的线性同余伪随机,不是 Math.random(),同一文件、同一 seed、同一 count 必然得到同一批记录(已写入测试断言)。
Q:evenly 和 random 该怎么选?
想知道「遍及全文件」的形态用 evenly;想知道「任意几条长什么样」用 random;看最新数据用 tail。
Q:project_fields 输出里的 - 是什么意思?
表示该条记录里这个字段不存在(路径任一层缺失)。它是结构性差异的信号,可用 missing 参数换成别的占位符。
Q:能处理几百 MB 的文件吗?
单文件默认上限 10 MB、max_size 最高 100 MB,且 max_lines 最多解析 10 万行。超出部分会被截断并提示。真正的超大文件流式处理在 RoadMap 的 v0.3。
Q:解析时会不会把数据写回文件? 不会。本插件只读,不做格式化回写。需要修改 JSONL 请用编辑器或脚本处理。
源码与发布地址
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-jsonl-stream
- npm:https://www.npmjs.com/package/dsh-jsonl-stream
许可证
MIT
