JSON Toolkit

Pengesahan JSON dalam CI: Saluran dengan jsonlint, ajv dan jq

Inti pati: Pengesahan sintaks membuktikan fail boleh dihuraikan; pengesahan skema membuktikan medan mematuhi kontrak. Dalam CI, yang penting ialah kod keluar yang tidak kabur, lokasi ralat dan laluan pembaikan.

Pertengahan~10 min bacaanDiterbitkan 2026-10-31Dikemas kini 2026-10-31
Kulit Pengesahan JSON dalam CI

Kesimpulan utama: dalam CI, biarkan jq empty mengendalikan sintaks, ajv-cli mengendalikan struktur (check-jsonschema untuk pasukan berbilang format), dan Prettier mengendalikan gaya; rantaikan mengikut lapisan dan berhenti pada kegagalan pertama.

Lulus penghurai dalam editor setempat anda tidak bermakna fail itu sesuai untuk CI; lulus CI juga tidak bermakna medan sepadan dengan kontrak.

1. Pisahkan pengesahan sintaks daripada pengesahan skema

Frasa "pengesahan JSON" digunakan terlalu luas, sebab itulah pasukan sering memilih satu alat untuk menyelesaikan dua masalah berbeza:

Lapisan Soalan yang dijawab Alatan tipikal Apa maksud kegagalan
Sintaks Adakah fail ini JSON yang sah? jq empty, jsonlint, python -m json.tool Kurungan, koma, tanda petik atau pengekodan rosak
Skema Adakah medan, jenis dan sifat wajib sepadan dengan kontrak? ajv-cli, check-jsonschema Fail dihuraikan, tetapi struktur perniagaan salah
Gaya Adakah indentasi dan susunan kunci konsisten? Prettier, jq -S Pemformatan tidak konsisten dan diff bising

Lapisan ini tidak boleh menggantikan satu sama lain. Fail yang lulus sintaks masih boleh gagal skema: {"price": "12.5"} ialah JSON yang sah, tetapi jika skema memerlukan price sebagai nombor, ia tidak diterima. Sebaliknya, walau selengkap mana pun skema, fail yang hilang kurungan penutup tidak akan pernah dapat dikompil dengan skema itu.

Jadi saluran harus menjalankan sintaks dahulu, struktur kedua, dan gaya terakhir. Berhenti sebaik sahaja satu lapisan gagal, jika tidak ralat penghuraian menyamar sebagai ralat medan.

2. Lapisan sintaks: jq empty ialah pilihan kebergantungan minimum

Jika jq sudah ada dalam imej CI, pengesahan sintaks hampir tidak berharga:

jq empty data.json

jq empty tidak menghasilkan output; ia hanya menghuraikan fail. Ia keluar dengan 0 pada kejayaan dan kod bukan sifar ditambah maklumat baris/lajur pada kegagalan. Itu menjadikannya lebih ringan daripada menarik masuk pepohon kebergantungan Node penuh, dan sesuai sebagai pintu pertama.

Semasa mengesahkan fail JSON secara kelompok dalam repositori, kecualikan node_modules, output binaan dan cache pihak ketiga:

find . -name '*.json' \
  -not -path './node_modules/*' \
  -not -path './dist/*' \
  -print0 | xargs -0 -n1 jq empty

-print0 dan xargs -0 mengendalikan ruang dalam nama fail, manakala -n1 memastikan satu fail bagi setiap pemanggilan supaya mesej ralat mengenal pasti penyebabnya. Jangan serahkan ratusan fail kepada satu proses; mesej ralat akan saling menimpa.

jsonlint ialah pilihan biasa yang lain, biasanya dipanggil sebagai npx jsonlint -q data.json, di mana -q hanya mencetak ralat. Ia melaporkan nombor baris dan lajur, tetapi penyelenggaraannya kurang aktif berbanding jq, dan versi berbeza bertoleransi secara berbeza terhadap BOM dan komen. Anggap ia sebagai pemeriksa sintaks yang lebih mudah dibaca, bukan sebagai pengesah skema.

3. Lapisan skema: asas ajv-cli validate

Ajv ialah pengesah skema yang paling banyak digunakan dalam ekosistem JavaScript, dan ajv-cli mendedahkannya sebagai alat baris arahan:

ajv validate -s schema.json -d data.json

-s menunjuk ke fail skema dan -d ke data yang sedang disahkan. Pada kegagalan proses keluar bukan sifar, jadi CI gagal serta-merta. Projek sebenar biasanya menambah dua bendera:

npx ajv-cli validate \
  -s schemas/order.json \
  -d 'fixtures/orders/*.json' \
  --strict=false \
  --errors=text

--strict=false membantu dengan skema lama: mod ketat menganggap kata kunci tidak dikenali dan pengisytiharan required yang mencurigakan sebagai ralat, yang gagal dilakukan oleh banyak skema warisan. --errors=text menghasilkan output yang boleh dibaca manusia, manakala struktur JSON lalai lebih baik untuk mesin. Pilih berdasarkan siapa yang menggunakan hasilnya.

Versi draf skema juga mesti sepadan. Versi utama Ajv menyokong draf berbeza secara lalai, dan ajv-cli boleh memilih satu dengan --spec=draft7, --spec=draft2019 atau --spec=draft2020. Jika skema mengisytiharkan $schema: "https://json-schema.org/draft/2020-12/schema" tetapi CLI mengompilnya sebagai draf-07, sesetengah kata kunci diabaikan secara senyap. Untuk lebih lanjut tentang penulisan skema dan perbezaan versi, lihat Permulaan dengan JSON Schema.

Pengesahan format ialah satu lagi keperluan yang kerap. Kata kunci format adalah anotasi sahaja secara lalai; untuk menjadikan email, date-time dan uri benar-benar menguatkuasakan sesuatu, muatkan ajv-formats:

npx ajv-cli validate -c ajv-formats -s schema.json -d data.json

Langkah ini mudah terlupa, dan hasilnya ialah medan e-mel menerima not-an-email. Sebelum menghantar, beri saluran satu rekod yang sengaja tidak sah; itu membuktikan peraturan aktif jauh lebih baik daripada membaca dokumentasi sepuluh kali.

check-jsonschema: berbilang format dan ralat yang lebih mesra

Jika pasukan mengendalikan YAML, TOML atau konfigurasi GitHub Actions sebagai tambahan kepada JSON, check-jsonschema lebih mudah:

check-jsonschema --schemafile schemas/config.json config/app.json
check-jsonschema --schemafile schemas/pipeline.json .github/workflows/ci.yml

Kelebihan praktikalnya:

  1. Sokongan YAML asli, yang sesuai untuk fail yang "berbentuk JSON tetapi ditulis dalam YAML", seperti manifes Kubernetes dan konfigurasi CI.
  2. Ralat termasuk laluan fail, nombor baris dan laluan medan, menjadikan kos lokasi rendah.
  3. Cangkuk pre-commit disediakan, jadi integrasi murah.
  4. Ia boleh menarik skema biasa daripada SchemaStore, tetapi juga menerima fail setempat, mengelakkan kebergantungan rangkaian.

Dalam pasukan merentas bahasa, Python sering sudah ada, jadi memasang dan menaik taraf check-jsonschema lebih ringan daripada menyelenggara rantaian alat Node. Biarkan jq mengendalikan sintaks dan alat ini mengendalikan struktur; gabungan itu mempunyai kos penyelenggaraan yang sangat rendah.

4. Kod keluar ialah satu-satunya isyarat CI yang boleh dipercayai

Walau seberapa kemas output, CI hanya membaca kod keluar. Tiga perangkap biasa:

Gejala Punca Pembaikan
Ralat wujud tetapi CI hijau Perintah berakhir dengan `
Tiada ralat tetapi CI merah diff menganggap "perbezaan ditemui" sebagai kegagalan Bezakan "perbezaan" daripada "ralat pelaksanaan"
Output ralat dipotong Output berbilang fail selari saling menimpa Jalankan secara bersiri atau cetak setiap fail

Ingat semantik kod keluar jq: penghuraian normal mengembalikan 0; dengan -e, hasil ungkapan false atau null mengembalikan 1; ralat penggunaan dan fail hilang mengembalikan 2; ralat kompilasi skrip mengembalikan 3. Alat skema biasanya menggunakan 0 untuk kejayaan, 1 untuk kegagalan pengesahan, dan 2 untuk ralat alat atau argumen. Semasa menulis pembalut, jangan runtuhkan setiap kod bukan sifar menjadi "data itu salah", jika tidak kegagalan persekitaran akan disalah diagnosis sebagai masalah kandungan.

5. pre-commit: tangkap masalah sebelum commit

Nilai pre-commit bukanlah "satu semakan lagi"; ia memberikan maklum balas kepada pembangun dalam satu minit dan bukannya selepas larian CI sepuluh minit. Konfigurasi minimum kelihatan seperti ini:

repos:
  - repo: https://github.com/python-jsonschema/check-jsonschema
    rev: 0.33.0
    hooks:
      - id: check-jsonschema
        files: ^configs/.*\.json$
        args:
          - --schemafile
          - schemas/config.json
  - repo: local
    hooks:
      - id: jq-syntax
        name: jq syntax check
        entry: jq empty
        language: system
        files: ^configs/.*\.json$

Dua butiran penting:

  • files harus sepadan dengan direktori yang perlu disahkan sahaja. Jangan jalankan cangkuk terhadap node_modules atau fail yang dijana.
  • Cangkuk setempat mengandaikan jq dipasang pada mesin pembangun. Dokumentasikan keperluan itu, atau tukar kepada cangkuk berkontena.

Jika projek sudah menggunakan Husky dan lint-staged, gabungkan mereka secara terus:

{
  "lint-staged": {
    "configs/*.json": ["jq empty", "prettier --check"]
  }
}

Ingat bahawa lint-staged menghantar senarai fail yang di-stage, jadi perintah mesti menerima berbilang laluan. Kedua-dua jq empty dan prettier --check menerimanya. Jangan biarkan cangkuk mengimbas keseluruhan repositori; commit akan menjadi ketara lebih perlahan.

6. GitHub Actions: saluran yang boleh anda salin

Aliran kerja di bawah melakukan pengesahan sintaks, pengesahan skema, dan mengekalkan laporan pada kegagalan:

name: json-validate

on:
  push:
    paths:
      - 'schemas/**'
      - 'fixtures/**'
  pull_request:

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Syntax check
        run: |
          find fixtures -name '*.json' -print0 | xargs -0 -n1 jq empty
      - name: Schema check
        run: |
          npx --yes ajv-cli validate \
            -s schemas/order.json \
            -d 'fixtures/orders/*.json' \
            --strict=false \
            --errors=text

Penapis paths menghalang perubahan dokumentasi sahaja daripada mencetuskan pengesahan. npx --yes sesuai untuk repositori tanpa kebergantungan yang dipasak; projek produksi patut menambah ajv-cli ke devDependencies dan memasak versinya. Tanpa kunci, keluaran huluan yang mengubah draf lalai atau mod ketat boleh menjadikan saluran merah dalam sekelip mata.

7. Lokasi ralat: daripada nombor baris kepada laluan medan

Separuh nilai pengesah ialah pengesanan; separuh lagi ialah lokasi. Belajar membaca tiga jenis output:

  1. Ralat sintaks: jq melaporkan baris dan lajur, selalunya dengan petikan berdekatan. Betulkan kurungan dan koma dahulu; jangan syak pengekodan serta-merta.
  2. Ralat skema: instancePath Ajv menunjuk ke lokasi data (contohnya /items/0/price), schemaPath menunjuk ke peraturan (contohnya #/properties/items/items/properties/price/type), dan keyword menamakan kekangan yang dilanggar.
  3. Ralat format: apabila semakan format gagal, mesej selalunya hanya menyatakan "must match format "email"". Gabungkannya dengan instancePath untuk mengenal pasti medan.

Tampalkan instancePath ke dalam rekod siasatan; ia jauh lebih berguna daripada dinding JSON. Untuk tatasusunan, indeks berangka juga memberitahu anda rekod mana yang gagal. Jika kunci perniagaan lebih intuitif, tambah baris pemetaan selepasnya, seperti items[0].id = ORD-042.

Kesilapan skema biasa, seperti penggunaan berlebihan additionalProperties: false atau menulis cabang oneOf yang sebenarnya bertindih, diliputi dalam Perangkap biasa penjanaan JSON Schema. Peraturan pengesahan yang salah lebih berbahaya daripada tiada pengesahan, kerana ia mencipta rasa selamat yang palsu.

8. Jadual pemilihan alat

Keperluan Alat disyorkan Mengapa Awas terhadap
Sintaks sahaja jq empty Sifar kebergantungan, pantas, kod keluar jelas Ruang dalam nama fail semasa larian kelompok
Ralat baris/lajur lebih mesra jsonlint Output boleh dibaca Aktiviti penyelenggaraan terhad
Pengesahan JSON Schema ajv-cli Ekosistem matang, ralat berstruktur Selaraskan versi draf dan muatkan sokongan format
Repositori campuran JSON dan YAML check-jsonschema Berbilang format, mesra pre-commit Sumber skema dan akses rangkaian
Maklum balas pantas sebelum commit pre-commit / lint-staged Hanya memproses fail yang di-stage Cangkuk mesti menerima berbilang laluan
Pemformatan konsisten Prettier Diguna pakai secara meluas Gunakan --check apabila anda tidak mahu menulis semula fail

Satu cadangan terakhir: sahkan bahawa saluran benar-benar gagal dengan memberinya satu rekod yang sengaja tidak sah dahulu. Risiko terbesar bukanlah konfigurasi yang rumit; ia konfigurasi yang tidak pernah berkesan. Menganggap "ia boleh gagal" sebagai kriteria penerimaan lebih boleh dipercayai daripada menganggap "ia lulus" sebagai kriteria. Untuk rantaian alat baris arahan yang lebih luas, teruskan dengan Editor, baris arahan dan automasi.

Soalan Lazim

Patutkah saya menggunakan jq empty atau jsonlint?

Utamakan jq empty dalam CI: sifar kebergantungan, permulaan pantas, dan semantik kod keluar yang jelas. Gunakan jsonlint apabila anda memerlukan mesej baris/lajur yang lebih mesra atau sedang menyiasat secara setempat. Kedua-duanya hanya melakukan pengesahan sintaks; tiada satu pun menyemak struktur medan.

Mengapa ajv melaporkan kata kunci tidak dikenali?

Mula-mula sahkan bahawa draf $schema skema sepadan dengan versi yang digunakan CLI. Banyak ralat "kata kunci tidak dikenali" ialah kata kunci draf baharu yang ditemui oleh pengompil lama. Jika versi sepadan, semak kesilapan taip. --strict=false boleh memastikan skema warisan berfungsi, tetapi jangan bergantung padanya jangka panjang untuk menyembunyikan masalah sebenar.

Pengesahan skema lulus, tetapi API masih gagal. Mengapa?

Skema mengesahkan struktur, bukan semantik perniagaan. Contohnya, status mungkin rentetan dengan enum sah, manakala mesin keadaan melarang peralihan terus daripada paid ke refunded. Peraturan seperti itu tergolong dalam kod atau kekangan pangkalan data, bukan dalam JSON Schema.

Bagaimana saya mencari medan yang gagal dengan cepat?

Baca instancePath atau nombor baris daripada output alat. instancePath Ajv ialah JSON Pointer yang menunjuk terus ke data; check-jsonschema melaporkan fail dan baris. Rekodkan laluan dan petakannya kepada kunci perniagaan; mencari isu biasanya mengambil masa beberapa minit.

Patutkah pre-commit menjalankan pengesahan penuh?

Tidak. pre-commit patut memproses fail yang di-stage sahaja untuk memastikan commit pantas. Imbasan penuh tergolong dalam CI atau tugas berjadual. Pembahagiannya mudah: larian setempat mengutamakan kelajuan, CI mengutamakan kesempurnaan.