
Komponen bereaksi untuk mengedit atau melihat data JSON/objek

Penting
Breaking Changes:
theme . Tema bawaan sekarang harus diimpor secara terpisah dan dilewati, daripada hanya menyebutkan tema sebagai string. Ini lebih baik untuk goncangan pohon, jadi tema yang tidak digunakan tidak akan dibundel dengan bangunan Anda. Lihat Tema & GayasetData dan tidak menggunakan onUpdate untuk memperbarui data Anda secara eksternal. Lihat Negara Bagian Pengelola. npm i json-edit-react
atau
yarn add json-edit-react
import { JsonEditor } from 'json-edit-react'
// In your React component:
return
< JsonEditor
data = { jsonData }
setData = { setJsonData } // optional
{ ... otherProps } /> (untuk pengguna akhir)
Ini sangat jelas (klik ikon "Edit" untuk diedit, dll.), Tetapi ada beberapa cara yang tidak jelas untuk berinteraksi dengan editor:
Cmd/Ctrl/Shift-Enter untuk menambahkan baris baru ( Enter mengirimkan nilai)Enter untuk baris baru, dan Cmd/Ctrl/Shift-Enter untuk dikirimEscape untuk membatalkan pengeditanCmd/Ctrl akan menyalin jalur ke node yang dipilih daripada nilainyajsonParse PROP. Satu -satunya nilai yang diperlukan adalah data (meskipun Anda perlu menyediakan metode setData untuk memperbarui data Anda).
| menopang | jenis | bawaan | keterangan |
|---|---|---|---|
data | object|array | Data yang akan ditampilkan / diedit | |
setData | object|array => void | Metode untuk memperbarui objek data Anda. Lihat Status pengelolaan di bawah ini untuk catatan tambahan. | |
rootName | string | "data" | Nama untuk ditampilkan di editor sebagai akar objek data. |
onUpdate | UpdateFunction | Fungsi untuk dijalankan setiap kali nilai diperbarui (edit, hapus atau tambahkan) di editor. Lihat Fungsi Pembaruan. | |
onEdit | UpdateFunction | Fungsi untuk dijalankan kapan pun nilai diedit . | |
onDelete | UpdateFunction | Fungsi untuk dijalankan setiap kali nilai dihapus . | |
onAdd | UpdateFunction | Fungsi untuk dijalankan setiap kali properti baru ditambahkan . | |
onChange | OnChangeFunction | Fungsi untuk memodifikasi/membatasi input pengguna saat mereka mengetik - lihat fungsi Onchange. | |
onError | OnErrorFunction | Fungsi untuk dijalankan setiap kali komponen melaporkan kesalahan - lihat OnErrorFunction. | |
showErrorMessages | boolean | true | Apakah komponen harus menampilkan pesan kesalahannya sendiri atau tidak (Anda mungkin hanya ingin menonaktifkan ini jika Anda menyediakan fungsi onError Anda sendiri) |
enableClipboard | boolean|CopyFunction | true | Apakah akan mengaktifkan tombol "Salin ke Clipboard" di UI. Jika suatu fungsi disediakan, true diasumsikan dan fungsi ini akan dijalankan setiap kali item disalin. |
indent | number | 3 | Tentukan jumlah indentasi untuk setiap tingkat sarang dalam data yang ditampilkan. |
collapse | boolean|number|FilterFunction | false | Mendefinisikan node mana dari pohon JSON yang akan ditampilkan "dibuka" di UI pada beban. Jika boolean , itu akan menjadi semua atau tidak sama sekali. number menentukan kedalaman sarang setelah node akan ditutup. Untuk kontrol yang lebih baik, suatu fungsi dapat disediakan - lihat fungsi filter. |
collapseAnimationTime | number | 300 | Waktu (dalam milidetik) untuk animasi transisi saat meruntuhkan node koleksi. |
restrictEdit | boolean|FilterFunction | false | Jika true , tidak ada pengeditan yang diizinkan. Fungsi dapat disediakan untuk lebih spesifik - lihat fungsi filter |
restrictDelete | boolean|FilterFunction | false | Seperti halnya restrictEdit tetapi untuk penghapusan |
restrictAdd | boolean|FilterFunction | false | Seperti halnya restrictEdit tetapi untuk menambahkan properti baru |
restrictTypeSelection | boolean|DataType[]|TypeFilterFunction | true | Untuk membatasi tipe data yang dapat dipilih pengguna. Dapat berupa daftar tipe data (misalnya [ 'string', 'number', 'boolean', 'array', 'object', 'null' ] ) atau boolean. Fungsi dapat disediakan - harus mengambil input yang sama dengan FilterFunction di atas, tetapi output harus boolean | DataType[] . |
restrictDrag | boolean|FilterFunction | true | Atur ke false untuk mengaktifkan fungsi seret dan lepas. Lihat drag-n-drop |
searchText | string | undefined | Visibilitas data akan difilter dengan mencocokkan dengan nilai, menggunakan metode yang ditentukan di bawah ini di searchFilter |
searchFilter | "key"|"value"|"all"|SearchFilterFunction | undefined | Tentukan bagaimana searchText harus dicocokkan untuk memfilter item yang terlihat. Lihat Pencarian/Penyaringan |
searchDebounceTime | number | 350 | Debounce Time saat searchText berubah |
keySort | boolean|CompareFunction | false | Jika true , tombol objek akan dipesan (menggunakan JS .sort() ). Fungsi perbandingan juga dapat disediakan untuk menentukan perilaku penyortiran. |
showArrayIndices | boolean | true | Apakah akan menampilkan indeks atau tidak (sebagai kunci properti) untuk elemen array. |
showStringQuotes | boolean | true | Apakah akan menampilkan nilai string atau tidak di "kutipan". |
showCollectionCount | boolean|"when-closed" | true | Apakah akan menampilkan jumlah item di setiap koleksi (objek atau array). |
defaultValue | any|DefaultValueFilterFunction | null | Ketika properti baru ditambahkan, itu diinisialisasi dengan nilai ini. Fungsi dapat disediakan dengan input yang hampir sama dengan FilterFunction S, tetapi harus menghasilkan nilai. Ini memungkinkan nilai default yang berbeda untuk digunakan tergantung pada status data (misalnya default untuk tingkat atas adalah objek, tetapi string di tempat lain.) |
stringTruncate | number | 250 | Nilai string lebih panjang dari banyak karakter ini akan ditampilkan terpotong (dengan ... ). String penuh akan selalu terlihat saat mengedit. |
translations | Objek LocalisedStrings | { } | String UI (seperti pesan kesalahan) dapat diterjemahkan dengan meneruskan objek yang berisi nilai string lokal (hanya ada beberapa). Lihat Lokalisasi |
theme | ThemeInput | default | Salah satu tema bawaan (diimpor secara terpisah), atau objek yang menentukan beberapa atau semua properti tema. Lihat tema. |
className | string | Nama kelas CSS untuk diterapkan ke komponen. Dalam kebanyakan kasus, menentukan properti theme akan lebih mudah. | |
id | string | Nama untuk atribut id HTML pada wadah komponen utama. | |
icons | {[iconName]: JSX.Element, ... } | { } | Ganti ikon bawaan dengan menentukannya di sini. Lihat tema. |
minWidth | number|string (nilai CSS) | 250 | Lebar minimum untuk wadah editor. |
maxWidth | number|string (nilai CSS) | 600 | Lebar maksimum untuk wadah editor. |
rootFontSize | number|string (nilai CSS) | 16px | Ukuran font "dasar" dari mana semua sizing lain diturunkan (dalam em s). Dengan mengubah ini, Anda akan mengukur seluruh komponen. wadah. |
customNodeDefinitions | CustomNodeDefinition[] | Anda dapat memberikan komponen khusus untuk mengganti node spesifik di pohon data, sesuai dengan fungsi kondisi. Lihat Lihat Node Kustom untuk lebih detail. (Komponen khusus sederhana untuk mengubah string URL menjadi tautan aktif disediakan di paket utama - lihat di sini) | |
customText | CustomTextDefinitions | Selain melokalkan string teks komponen, Anda juga dapat mengubahnya secara dinamis , tergantung pada data. Lihat teks khusus untuk detail lebih lanjut. | |
customButtons | CustomButtonDefinition[] | [] | Anda dapat menambahkan tombol Anda sendiri ke panel Edit Tombol jika Anda ingin dapat melakukan operasi khusus pada data. Lihat tombol khusus |
jsonParse | (input: string) => JsonData | JSON.parse | Saat mengedit blok JSON secara langsung, Anda mungkin ingin mengizinkan beberapa input "Looser" - misalnya 'kutipan tunggal', koma trailing, atau nama lapangan yang tidak dikutip. Dalam hal ini, Anda dapat memberikan metode parsing JSON pihak ketiga. Saya merekomendasikan JSON5, yang digunakan dalam demo |
jsonStringify | (data: JsonData) => string | (data) => JSON.stringify(data, null, 2) | Demikian pula, Anda dapat mengesampingkan presentasi default dari string JSON saat mulai mengedit JSON. Anda dapat menyediakan parameter pemformatan yang berbeda ke JSON.stringify() , atau memberikan opsi pihak ketiga, seperti JSON5 yang disebutkan di atas. |
errorMessageTimeout | number | 2500 | Waktu (dalam milidetik) untuk menampilkan pesan kesalahan di UI. |
keyboardControls | KeyboardControls | Seperti yang dijelaskan di atas | Angkanya beberapa atau semua kontrol keyboard. Lihat Kustomisasi Keyboard untuk detailnya. |
insertAtTop | boolean| "object | "array" | false | Jika true , masukkan nilai baru di bagian atas daripada bawah. Dapat mengatur perilaku hanya untuk array atau objek dengan mengatur ke "object" atau "array" masing -masing. |
Dianjurkan agar Anda mengelola status data sendiri di luar komponen ini - cukup lulus dalam metode setData , yang disebut secara internal untuk memperbarui data Anda. Namun, ini bukan wajib - jika Anda tidak memberikan metode setData , data akan dikelola secara internal, yang akan baik -baik saja jika Anda tidak melakukan apa pun dengan data. Alternatifnya adalah dengan menggunakan fungsi pembaruan untuk memperbarui data Anda secara eksternal, tetapi ini tidak disarankan kecuali dalam keadaan khusus karena Anda dapat mengalami masalah menjaga data Anda tetap sinkron dengan keadaan internal (yang ditampilkan), serta re-render yang tidak perlu. Fungsi pembaruan harus idealnya hanya digunakan untuk mengimplementasikan efek samping, memeriksa kesalahan, atau bermutasi data sebelum mengaturnya dengan setData .
Panggilan balik yang akan dieksekusi setiap kali pembaruan data (edit, hapus atau tambahkan) terjadi dapat disediakan. Anda mungkin ingin menggunakan ini untuk memperbarui beberapa keadaan eksternal, melakukan panggilan API, memodifikasi data sebelum menyimpannya, atau memvalidasi struktur data terhadap skema JSON. Jika Anda menginginkan fungsi yang sama untuk semua pembaruan, maka hanya prop onUpdate sudah cukup. Namun, jika Anda memerlukan sesuatu yang berbeda untuk pengeditan, penghapusan, dan penambahan, maka Anda dapat memberikan fungsi pembaruan terpisah melalui props onEdit , onDelete dan onAdd .
Fungsi akan menerima objek berikut sebagai parameter:
{
newData , // data state after update
currentData , // data state before update
newValue , // the new value of the property being updated
currentValue , // the current value of the property being updated
name , // name of the property being updated
path // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name")
}Fungsi tidak dapat mengembalikan apa pun (dalam hal ini data diperbarui secara normal), atau nilai untuk mewakili keberhasilan/kegagalan, nilai kesalahan, atau data yang dimodifikasi. Nilai pengembalian bisa menjadi salah satu dari yang berikut, dan ditangani sesuai:
true / void / undefined : Data terus memperbarui seperti biasafalse : menganggap pembaruan sebagai kesalahan, jadi data tidak diperbarui (kembali ke nilai sebelumnya), dan pesan kesalahan umum ditampilkan di UIstring : Juga dianggap sebagai kesalahan, jadi tidak ada pembaruan data, tetapi pesan kesalahan UI akan menjadi string yang disediakan Anda[ "value", <value> ] : Memberitahu komponen untuk menggunakan <value> yang dikembalikan alih -alih data input. Anda dapat menggunakan ini untuk secara otomatis memodifikasi input pengguna - misalnya, menyortir array, atau memasukkan bidang cap waktu ke dalam suatu objek.[ "error", <value> ] : Sama seperti string , tetapi dalam format tuple yang lebih panjang. Mirip dengan fungsi pembaruan, fungsi onChange dijalankan saat input pengguna berubah. Anda dapat menggunakan ini untuk membatasi atau membatasi input pengguna - misalnya membatasi angka pada nilai positif, atau mencegah jeda garis dalam string. Fungsi harus mengembalikan nilai untuk memperbarui bidang input pengguna, jadi jika tidak ada perubahan yang dibuat, cukup kembalikan tidak dimodifikasi.
Objek input mirip dengan input fungsi pembaruan, tetapi tanpa bidang newData (karena operasi ini terjadi sebelum data diperbarui).
// in <JsonEditor /> props
onChange = ( { newValue , name } ) => {
if ( name === "age" && newValue < 0 ) return 0 ;
if ( name === "age" && newValue > 100 ) return 100 ;
return newValue
} onChange = ( { newValue , name } ) => {
if ( name === 'name' && typeof newValue === "string" )
return newValue . replace ( / [^a-zA-Zs]|n|r / gm , '' ) ;
return newValue ;
} Biasanya, komponen akan menampilkan pesan kesalahan sederhana setiap kali kondisi kesalahan terdeteksi (misalnya input JSON yang tidak valid, tombol duplikat, atau kesalahan khusus yang dikembalikan oleh fungsi onUpdate )). Namun, Anda dapat memberikan panggilan balik onError Anda sendiri untuk mengimplementasikan UI kesalahan Anda sendiri, atau menjalankan efek samping tambahan. (Dalam kasus sebelumnya, Anda mungkin ingin menonaktifkan prop showErrorMessages juga.) Input ke panggilan balik mirip dengan panggilan balik lainnya:
{
currentData , // data state before update
currentValue , // the current value of the property being updated
errorValue , // the erroneous value that failed to update the property
name , // name of the property being updated
path , // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name"),
error : {
code , // one of 'UPDATE_ERROR' | 'DELETE_ERROR' | 'ADD_ERROR' | 'INVALID_JSON' | 'KEY_EXISTS'
message // the (localised) error message that would be displayed
}
}(Contoh UI Kesalahan Kustom dapat dilihat dalam demo dengan set data "Node Kustom" - ketika Anda memasukkan pemberitahuan JSON JSON yang tidak valid A "Toast" ditampilkan alih -alih pesan kesalahan komponen normal.)
Panggilan balik serupa dieksekusi setiap kali item disalin ke clipboard (jika diteruskan ke prop enableClipboard ), tetapi dengan parameter input yang berbeda:
key // name of the property being copied
path // path to the property
value // the value copied to the clipboard
type // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
stringValue // A nicely stringified version of `value`
// (i.e. what the clipboard actually receives)Karena sangat sedikit umpan balik pengguna saat mengklik "Salin", ide yang bagus adalah menyajikan semacam pemberitahuan dalam panggilan balik ini.
Selain tombol "Salin", "Edit" dan "Hapus" yang muncul dengan setiap nilai, Anda dapat menambahkan tombol Anda sendiri jika Anda perlu mengizinkan beberapa operasi khusus pada data. Berikan serangkaian definisi tombol di Prop customButtons , dalam struktur definisi berikut:
{
Element : React . FC ,
onClick : ( nodeData : NodeData , e : React . MouseEvent ) => void
} Di mana NodeData adalah struktur data yang sama yang diterima oleh "fungsi pembaruan" sebelumnya.
Anda dapat mengontrol node mana dari struktur data yang dapat diedit, dihapus, atau ditambahkan ke, atau tipe data mereka diubah, dengan melewati fungsi filter. Ini akan dipanggil pada setiap properti dalam data dan atribut akan ditegakkan tergantung pada apakah fungsi mengembalikan true atau false (cara true tidak dapat diedit).
Fungsi menerima objek berikut:
{
key , // name of the property
path , // path to the property (as an array of property keys)
level , // depth of the property (with 0 being the root)
index , // index of the node within its collection (based on display order)
value , // value of the property
size , // if a collection (object, array), the number of items (null for non-collections)
parentData , // parent object containing the current node
fullData // the full (overall) data object
collapsed // whether or not the current node is in a
// "collapsed" state (only for Collection nodes)
} Fungsi filter juga tersedia untuk prop collapse , sehingga Anda dapat membuat data Anda muncul dengan koleksi yang sangat bersarang dibuka, sambil menciutkan yang lainnya, misalnya.
Untuk membatasi tipe data, fungsi filter (tipe) sedikit lebih canggih. Inputnya sama, tetapi output dapat berupa boolean (yang akan membatasi jenis yang tersedia untuk node yang diberikan untuk semua atau tidak sama sekali ), atau serangkaian tipe data yang harus dibatasi. Nilai yang tersedia adalah:
"string""number""boolean""null""object""array" Tidak ada fungsi pembatasan spesifik untuk mengedit nama kunci objek, tetapi mereka harus mengembalikan yang true untuk restrictEdit dan restrictDelete (dan restrictAdd untuk koleksi), karena mengubah nama kunci setara dengan menghapus properti dan menambahkan yang baru.
Anda juga dapat menetapkan nilai default dinamis dengan meneruskan fungsi filter ke prop defaultValue - inputnya sama dengan yang di atas, tetapi juga mengambil nilai key baru sebagai parameter kedua, sehingga nilai baru dapat bergantung pada penambahan kunci baru.
Menggunakan semua filter pembatasan ini bersama -sama dapat memungkinkan Anda untuk menegakkan skema data yang cukup canggih.
// in <JsonEditor /> props
restrictEdit = { ( { level } ) => level === 0 }id diedit: restrictEdit = { ( { key } ) => key === "id" }
// You'd probably want to include this in `restrictDelete` as well restrictDelete = { ( { size } ) => size !== null } restrictAdd = { ( { key } ) => key !== "address" && key !== "users" }
// "Adding" is irrelevant for non-collection nodesstring hanya dapat diubah menjadi string atau objek (untuk bersarang)null tidak diperbolehkan di mana punboolean harus tetap boolean restrictTypeSelection = { ( { path , value } ) => {
if ( path . includes ( 'user' ) ) return [ 'string' , 'number' , 'boolean' ]
if ( typeof value === 'boolean' ) return false
if ( typeof value === 'string' ) return [ 'string' , 'object' ]
return [ 'string' , 'number' , 'boolean' , 'array' , 'object' ] // no "null"
} }Selain mengontrol akses secara dinamis ke berbagai alat edit seperti yang dijelaskan di atas, dimungkinkan untuk melakukan validasi skema JSON penuh dengan membuat fungsi pembaruan yang meneruskan data ke pustaka validasi skema pihak ke-3 (misalnya AJV). Ini kemudian akan menolak input yang tidak valid, dan menampilkan kesalahan di UI (atau melalui fungsi OnError khusus). Anda dapat melihat contoh ini dalam demo dengan set data "JSON Schema Validation" (dan set data "node khusus").
Contoh fungsi validasi onUpdate (menggunakan AJV) bisa menjadi sesuatu seperti ini:
import { JsonEditor } from 'json-edit-react'
import Ajv from 'ajv'
import schema from './my-json-schema.json'
const ajv = new Ajv ( )
const validate = ajv . compile ( schema )
/// Etc....
// In the React component:
return
< JsonEditor
data = { jsonData }
onUpdate = { ( { newData } ) => {
const valid = validate ( newData )
if ( ! valid ) {
console . log ( 'Errors' , validate . errors )
const errorMessage = validate . errors
?. map ( ( error ) => ` ${ error . instancePath } ${ error . instancePath ? ': ' : '' } ${ error . message } ` )
. join ( 'n' )
// Send detailed error message to an external UI element, such as a "Toast" notification
displayError ( {
title : 'Not compliant with JSON Schema' ,
description : errorMessage ,
status : 'error' ,
} )
// This string returned to and displayed in json-edit-react UI
return 'JSON Schema error'
}
} }
{ ... otherProps } />Catatan
Ini adalah fitur baru dan harus dianggap "eksperimental". Harap berikan umpan balik atau saran untuk membantu memperbaikinya.
Properti restrictDrag mengontrol item mana (jika ada) dapat diseret ke posisi baru. Secara default, ini tidak aktif , jadi Anda harus menetapkan restrictDrag = false untuk mengaktifkan fungsionalitas ini. Seperti pembatasan edit di atas, properti ini juga dapat mengambil fungsi filter untuk kontrol berbutir halus. Ada beberapa pertimbangan tambahan, meskipun:
jsonb (Binary JSON), urutan utama tidak ada artinya, jadi saat berikutnya objek dimuat, kunci akan terdaftar secara abjad.restrictDrag berlaku untuk elemen sumber (yaitu simpul yang diseret), bukan tujuan.restrictDelete ), karena menyeret node ke tujuan baru pada dasarnya hanya menghapusnya dan menambahkannya kembali ke tempat lain. Data yang ditampilkan dapat difilter berdasarkan input pencarian dari pengguna. Input pengguna harus ditangkap secara mandiri (kami tidak menyediakan UI di sini) dan disahkan dengan prop searchText . Input ini didebalkan secara internal (waktu dapat diatur dengan prop searchDebounceTime ), jadi tidak perlu itu juga. Nilai -nilai yang diuji oleh searchText ditentukan dengan pencarian searchFilter . Secara default (tidak ada searchFilter yang ditentukan), itu akan cocok dengan nilai data (dengan pencocokan parsial yang tidak sensitif-yaitu input "ILB", akan cocok dengan nilai "bilbo").
Anda dapat menentukan apa yang harus dicocokkan dengan mengatur searchFilter ke "key" (mencocokkan nama properti), "value" (default yang dijelaskan di atas), atau "all" (cocokkan kedua properti dan nilai). Ini harus cukup untuk sebagian besar kasus penggunaan, tetapi Anda dapat menentukan SearchFilterFunction Anda sendiri. Fungsi pencarian adalah tanda tangan yang sama dengan filterfunctions di atas tetapi mengambil satu argumen tambahan untuk searchText , yaitu
( { key , path , level , value , ... etc } : FilterFunctionInput , searchText : string ) => boolean Ada dua fungsi pembantu ( matchNode() dan matchNodeKey() ) yang diekspor dengan paket yang mungkin membuat membuat fungsi pencarian Anda lebih mudah (ini adalah fungsi yang digunakan secara internal untuk kecocokan "key" dan "value" yang dijelaskan di atas). Anda dapat melihat apa yang mereka lakukan di sini.
Contoh fungsi pencarian khusus dapat dilihat dalam demo dengan set data "Daftar Klien" - fungsi pencarian cocok dengan nama dan nama pengguna, dan membuat seluruh objek "klien" terlihat ketika salah satu dari kecocokan itu, sehingga dapat digunakan untuk menemukan orang tertentu dan mengedit detail spesifik mereka:
( { path , fullData } , searchText ) => {
// Matches *any* node that shares a path (i.e. a descendent) with a matching name/username
if ( path ?. length >= 2 ) {
const index = path ?. [ 0 ]
return (
matchNode ( { value : fullData [ index ] . name } , searchText ) ||
matchNode ( { value : fullData [ index ] . username } , searchText )
)
} else return false
} Ada sedikit pilihan tema bawaan (seperti yang terlihat di aplikasi demo). Untuk menggunakan salah satunya, cukup impor dari paket dan lewati sebagai prop tema:
import { JsonEditor , githubDarkTheme } from 'json-edit-react'
// ...other imports
const MyApp = ( ) => {
const [ data , setData ] = useState ( { one : 1 , two : 2 } )
return < JsonEditor
data = { data }
setData = { setData }
theme = { githubDarkTheme }
// other props...
/>
}Tema-tema berikut tersedia dalam paket (walaupun secara realistis, ini ada lebih banyak untuk menunjukkan kemampuannya-saya terbuka untuk tema bawaan yang lebih baik, jadi silakan membuat masalah dengan saran):
githubDarkThemegithubLightThememonoDarkThememonoLightThemecandyWrapperThemepsychedelicThemeNamun, Anda dapat meneruskan objek tema Anda sendiri, atau bagian daripadanya. Struktur tema adalah sebagai berikut (ini adalah definisi tema "default"):
{
displayName : 'Default' ,
fragments : { edit : 'rgb(42, 161, 152)' } ,
styles : {
container : {
backgroundColor : '#f6f6f6' ,
fontFamily : 'monospace' ,
} ,
collection : { } ,
collectionInner : { } ,
collectionElement : { } ,
dropZone : { } ,
property : '#292929' ,
bracket : { color : 'rgb(0, 43, 54)' , fontWeight : 'bold' } ,
itemCount : { color : 'rgba(0, 0, 0, 0.3)' , fontStyle : 'italic' } ,
string : 'rgb(203, 75, 22)' ,
number : 'rgb(38, 139, 210)' ,
boolean : 'green' ,
null : { color : 'rgb(220, 50, 47)' , fontVariant : 'small-caps' , fontWeight : 'bold' } ,
input : [ '#292929' , { fontSize : '90%' } ] ,
inputHighlight : '#b3d8ff' ,
error : { fontSize : '0.8em' , color : 'red' , fontWeight : 'bold' } ,
iconCollection : 'rgb(0, 43, 54)' ,
iconEdit : 'edit' ,
iconDelete : 'rgb(203, 75, 22)' ,
iconAdd : 'edit' ,
iconCopy : 'rgb(38, 139, 210)' ,
iconOk : 'green' ,
iconCancel : 'rgb(203, 75, 22)' ,
} ,
} Properti styles adalah yang utama untuk difokuskan. Setiap kunci ( property , bracket , itemCount ) mengacu pada bagian dari UI. Nilai untuk setiap kunci adalah :
string , dalam hal ini ditafsirkan sebagai warna (atau warna latar dalam kasus container dan inputHighlight )null ). Ini memungkinkan Anda untuk secara dinamis mengubah gaya berbagai elemen berdasarkan konten atau struktur.null . (Dalam array, item selanjutnya memiliki prioritas lebih tinggi)Sebagai contoh sederhana, jika Anda ingin menggunakan tema "githubdark", tetapi cukup ubah beberapa hal kecil, Anda akan menentukan sesuatu seperti ini:
// in <JsonEditor /> props
theme = { [
githubDarkTheme ,
{
iconEdit : 'grey' ,
boolean : { color : 'red' , fontStyle : 'italic' , fontWeight : 'bold' , fontSize : '80%' } ,
} ,
] } Yang akan mengubah nilai ikon "Edit" dan Boolean dari ini: 
ke dalam ini: 
Atau Anda dapat membuat tema sendiri dari awal dan menimpa seluruh objek tema.
Jadi, untuk meringkas, prop theme dapat mengambil :
"candyWrapperTheme"fragments , styles , displayName dll., Atau hanya bagian styles (pada level root)[ "<themeName>, {...overrides } ]Anda dapat bermain dengan pengeditan langsung tema di aplikasi demo dengan memilih "Edit tema ini!" Dari pemilih "Demo Data" (meskipun Anda tidak akan dapat membuat fungsi di JSON).
Cara lain untuk menata komponen adalah dengan menargetkan kelas CSS secara langsung. Setiap elemen dalam komponen memiliki nama kelas yang unik, jadi Anda harus dapat menemukannya di inspektur browser Anda dan menimpanya. Semua nama kelas dimulai dengan awalan jer- , misalnya jer-collection-header-row , jer-value-string .
Properti fragments di atas hanyalah kenyamanan untuk memungkinkan "fragmen" gaya berulang didefinisikan sekali dan dirujuk menggunakan alias. Misalnya, jika Anda ingin semua ikon Anda menjadi biru dan sedikit lebih besar dan berjarak, Anda mungkin mendefinisikan fragmen seperti itu:
fragments: { iconAdjust : { color : "blue" , fontSize : "110%" , marginRight : "0.6em" } }Kemudian di objek tema, cukup gunakan:
{
... ,
iconEdit : "iconAdjust" ,
iconDelete : "iconAdjust" ,
iconAdd : "iconAdjust" ,
iconCopy : "iconAdjust" ,
}Kemudian, ketika Anda ingin mengubahnya nanti, Anda hanya perlu memperbaruinya di satu tempat!
Fragmen juga dapat dicampur dengan sifat tambahan, dan bahkan fragmen lainnya, seperti itu:
iconEdit: [ "iconAdjust" , "anotherFragment" , { marginLeft : "1em" } ] Secara internal, semua ukuran dan jarak dilakukan di em S, tidak pernah px (selain dari rootFontSize , yang menetapkan ukuran "dasar"). Ini membuat penskalaan jauh lebih mudah - cukup ubah prop rootFontSize (atau atur fontSize pada wadah utama melalui penargetan kelas, atau tweake tema), dan saksikan seluruh skala komponen yang sesuai.
Ikon default dapat diganti, tetapi Anda perlu menyediakannya sebagai elemen React/HTML. Cukup tentukan salah satu atau semuanya di dalam prop icons , dikunci sebagai berikut:
icons = { {
add : < YourIcon />
edit : < YourIcon / >
delete : < YourIcon />
copy : < YourIcon / >
ok : < YourIcon / >
cancel : < YourIcon / >
chevron : < YourIcon / >
} }Komponen ikon perlu memiliki gaya sendiri, karena gaya tema tidak akan ditambahkan ke elemen khusus.
Lokalisasi implementasi Anda dengan meneruskan objek translations untuk menggantikan string default. Nilai kunci dan default (bahasa Inggris) adalah sebagai berikut:
{
ITEM_SINGLE : '{{count}} item' ,
ITEMS_MULTIPLE : '{{count}} items' ,
KEY_NEW : 'Enter new key' ,
ERROR_KEY_EXISTS : 'Key already exists' ,
ERROR_INVALID_JSON : 'Invalid JSON' ,
ERROR_UPDATE : 'Update unsuccessful' ,
ERROR_DELETE : 'Delete unsuccessful' ,
ERROR_ADD : 'Adding node unsuccessful' ,
DEFAULT_STRING : 'New data!' ,
DEFAULT_NEW_KEY : 'key' ,
} Anda dapat mengganti node tertentu di pohon data dengan komponen khusus Anda sendiri. Contoh mungkin untuk tampilan gambar, atau editor tanggal khusus, atau hanya untuk menambahkan beberapa bling visual. Lihat set data "node khusus" dalam demo interaktif untuk melihatnya beraksi. (Ada juga pemilih tanggal khusus yang muncul saat mengedit string ISO di set data lainnya.)
Node khusus disediakan di prop customNodeDefinitions , sebagai array objek dari struktur berikut:
{
condition , // a FilterFunction, as above
element , // React Component
customNodeProps , // object (optional)
hideKey , // boolean (optional)
defaultValue , // JSON value for a new instance of your component
showOnEdit // boolean, default false
showOnView // boolean, default true
showEditTools // boolean, default true
name // string (appears in Types selector)
showInTypesSelector , // boolean (optional), default false
// Only affects Collection nodes:
showCollectionWrapper // boolean (optional), default true
wrapperElement // React component (optional) to wrap *outside* the normal collection wrapper
wrapperProps // object (optional) -- props for the above wrapper component
} condition ini hanya fungsi filter, dengan parameter input yang sama ( key , path , value , dll.), Dan element adalah komponen reaksi. Setiap node dalam struktur data akan dijalankan melalui setiap fungsi kondisi, dan apa pun yang cocok akan diganti dengan komponen khusus Anda. Perhatikan bahwa jika sebuah simpul cocok dengan lebih dari satu kondisi definisi khusus (dari beberapa komponen), yang pertama akan digunakan, jadi tempatkan dalam array dalam urutan prioritas.
Komponen akan menerima semua alat peraga yang sama sebagai komponen simpul standar (lihat CodeBase), tetapi Anda dapat meneruskan alat peraga tambahan ke komponen Anda jika diperlukan melalui objek customNodeProps . Contoh menyeluruh dari pemilih tanggal khusus digunakan dalam demo (bersama dengan beberapa yang lebih mendasar presentasional lainnya), yang dapat Anda periksa untuk melihat cara memanfaatkan alat peraga standar dan beberapa alat peraga khusus. Lihat kode sumber di sini
Secara default, komponen Anda akan disajikan di sebelah kanan kunci properti, seperti nilai lainnya. Namun, Anda dapat menyembunyikan kunci itu sendiri dengan mengatur hideKey: true , dan komponen khusus akan mengambil seluruh baris. (Lihat kotak "disajikan oleh" di set data "node khusus" untuk contoh.)
Juga, secara default, komponen Anda akan diperlakukan sebagai elemen "display", yaitu itu akan muncul di penampil JSON, tetapi ketika mengedit, itu akan kembali ke antarmuka pengeditan standar. Namun, ini dapat diubah dengan tops showOnEdit , showOnView dan showEditTools . Misalnya, pemetik tanggal mungkin hanya diperlukan saat mengedit dan meninggalkan apa adanya untuk tampilan. Prop showEditTools mengacu pada ikon pengeditan (salin, tambahkan, edit, hapus) yang muncul di sebelah kanan setiap nilai pada hover. Jika Anda memilih untuk menonaktifkan ini tetapi Anda masih ingin komponen Anda memiliki mode "Edit", Anda harus menyediakan mekanisme UI Anda sendiri untuk beralih pengeditan.
Anda dapat mengizinkan pengguna untuk membuat instance baru dari node khusus Anda dengan memilihnya sebagai "tipe" di pemilih tipe saat mengedit/menambahkan nilai. Atur showInTypesSelector: true untuk mengaktifkan ini. Namun, jika ini diaktifkan, Anda juga perlu memberikan name (yang akan dilihat pengguna di pemilih) dan nilai defaultValue yang merupakan data yang dimasukkan ketika pengguna memilih "tipe" ini. ( defaultValue harus mengembalikan true jika melewati fungsi condition agar dapat segera ditampilkan menggunakan komponen khusus Anda.)
Komponen khusus dan definisi sederhana untuk mengubah string URL menjadi tautan yang dapat diklik disediakan dengan paket utama untuk Anda gunakan di luar kotak. Cukup impor dan gunakan seperti itu:
import { JsonEditor , LinkCustomNodeDefinition } from 'json-edit-react'
// ...Other stuff
return (
< JsonEditor
{ ... otherProps }
customNodeDefinitions = { [ LinkCustomNodeDefinition , ... otherCustomDefinitions ] }
/>
) Dalam kebanyakan kasus akan lebih disukai (dan lebih sederhana) untuk membuat node khusus untuk mencocokkan node nilai (yaitu bukan node pengumpulan array atau object ), yang merupakan apa yang ditunjukkan oleh semua contoh demo. Namun, jika Anda ingin menargetkan seluruh simpul koleksi, ada beberapa hal lain yang perlu diketahui:
children , itu hanya menjadi tanggung jawab komponen Anda untuk menanganinya.element biasa, yang akan ditampilkan di dalam kurung koleksi (yaitu muncul sebagai isi koleksi)wrapperElement opsional, yang ditampilkan di luar koleksi (alat peraga dapat disuplai seperti dijelaskan di atas dengan wrapperProps ). Sekali lagi, konten dalam (termasuk element khusus Anda) dapat ditampilkan menggunakan React children . Dalam contoh ini, perbatasan biru menunjukkan wrapperElement dan perbatasan merah menunjukkan element dalam: 
showCollectionWrapper (default true ), yang, ketika diatur ke false , menyembunyikan elemen koleksi di sekitarnya (yaitu hide/show chevron dan braket). Dalam hal ini, Anda harus memberikan mekanisme persembunyian/tampilan Anda sendiri dalam komponen Anda jika Anda menginginkannya. Dimungkinkan untuk mengubah berbagai string teks yang ditampilkan oleh komponen. Anda dapat melokalkannya, tetapi Anda juga dapat menentukan fungsi untuk mengganti teks yang ditampilkan berdasarkan kondisi tertentu. Misalnya, katakanlah kami ingin teks penghitungan properti (mis. 6 items secara default) memberikan ringkasan dari jenis node tertentu, yang bisa terlihat bagus saat runtuh. Misalnya (diambil dari demo):

Properti customText mengambil objek, dengan salah satu kunci yang dapat dilokalkan sebagai kunci, dengan fungsi yang mengembalikan string (atau null , yang menyebabkannya mundur ke string yang terlokalisasi atau default). Input ke fungsi -fungsi ini sama dengan fungsi filter, jadi dalam contoh ini, itu akan didefinisikan seperti itu:
// The function definition
const itemCountReplacement = ( { key , value , size } ) => {
// This returns "Steve Rogers (Marvel)" for the node summary
if ( value instanceof Object && 'name' in value )
return ` ${ value . name } ( ${ ( value ) ?. publisher ?? '' } )`
// This returns "X names" for the alias lists
if ( key === 'aliases' && Array . isArray ( value ) )
return ` ${ size } ${ size === 1 ? 'name' : 'names' } `
// Everything else as normal
return null
}
// And in component props...
. . . otherProps ,
customText = {
ITEM_SINGLE : itemCountReplacement ,
ITEMS_MULTIPLE : itemCountReplacement ,
} Kontrol keyboard default diuraikan di atas, tetapi dimungkinkan untuk menyesuaikan/mengganti ini. Lewati saja prop keyboardControls dengan tindakan yang ingin Anda ajukan. Objek konfigurasi default adalah:
{
confirm : 'Enter' , // default for all Value nodes, and key entry
cancel : 'Escape' ,
objectConfirm : { key : 'Enter' , modifier : [ 'Meta' , 'Shift' , 'Control' ] } ,
objectLineBreak : 'Enter' ,
stringConfirm : 'Enter' ,
stringLineBreak : { key : 'Enter' , modifier : 'Shift' } ,
numberConfirm : 'Enter' ,
numberUp : 'ArrowUp' ,
numberDown : 'ArrowDown' ,
booleanConfirm : 'Enter' ,
clipboardModifier : [ 'Meta' , 'Control' ] ,
collapseModifier : 'Alt' ,
}Jika (misalnya), Anda hanya ingin mengubah tindakan "konfirmasi" umum menjadi "CMD-enter" (di Mac), atau "Ctrl-Enter", Anda hanya akan masuk:
keyboardControls = {
confirm : {
key : "Enter" ,
modifier : [ "Meta" , "Control" ]
}
}Pertimbangan :
stringConfirm , numberConfirm , dan booleanConfirm jika mereka harus berbeda dari nilai confirm Anda.clipboardModifier default). Meskipun fungsionalitas undo/redo mungkin diinginkan dalam banyak kasus, ini tidak dibangun untuk komponen, karena dua alasan utama:
Beberapa fungsi, komponen, dan jenis pembantu yang mungkin berguna dalam implementasi Anda sendiri (dari membuat fungsi filter atau pembaruan, atau komponen khusus) diekspor dari paket:
themes : Objek yang berisi semua definisi tema bawaanLinkCustomComponent : Komponen yang digunakan untuk membuat hyperlinksLinkCustomNodeDefinition : Definisi Node Kustom untuk HyperlinksIconAdd , IconEdit , IconDelete , IconCopy , IconOk , IconCancel , IconChevron : Semua komponen ikon bawaanmatchNode , matchNodeKey : Pembantu untuk mendefinisikan fungsi pencarian khusustruncate : Fungsi untuk memotong string ke panjang yang ditentukan. Lihat di siniextract : Fungsi untuk mengekstrak nilai objek bersarang yang dalam dari jalur string. Lihat di siniassign : Fungsi untuk mengatur nilai objek yang dalam dari jalur string. Lihat di siniThemeName : Daftar literal string nama tema bawaanTheme : Objek Tema LengkapThemeInput : Jenis Input untuk Prop themeJsonEditorProps : Semua alat peraga input untuk komponen editor JSONJsonData : Objek data Utama - Struktur JSON apa pun yang validUpdateFunction , OnChangeFunction , OnErrorFunction FilterFunction , CopyFunction , SearchFilterFunction , CompareFunction , TypeFilterFunction , LocalisedString , CustomNodeDefinition , CustomTextDefinitions , CustomTextFunction ,TranslateFunction : Fungsi yang mengambil kunci lokalisasi dan mengembalikan string yang diterjemahkanIconReplacements : Jenis Input untuk Prop iconsCollectionNodeProps : Semua alat peraga dilewatkan secara internal ke node "Collection" (yaitu objek/array)ValueNodeProps : Semua alat peraga diteruskan secara internal ke node "nilai" (yaitu bukan objek/array)CustomNodeProps : Semua alat peraga yang diteruskan secara internal ke node khusus; Pada dasarnya sama dengan CollectionNodeProps dengan bidang customNodeProps ekstra untuk meloloskan alat peraga yang unik untuk komponen Anda`DataType : "string" | "number" | "boolean" | "null" | "object" | "array"KeyboardControls : Struktur untuk Prop Kustomisasi Keyboard Harap buka masalah: https://github.com/carlosnz/json-edit-react/issues
Fitur utama yang ingin saya perkenalkan adalah:
This component is heavily inspired by react-json-view, a great package that I've used in my own projects. However, it seems to have been abandoned now, and requires a few critical fixes, so I decided to create my own from scratch and extend the functionality while I was at it.
defaultValue function takes the new key as second parameteroverflow: clip setting based on animating statetrue to represent successsetData prop to discourage reliance on internal data state managementuseEffect hooksnull #90onError callback available for custom error handlingrootFontSize prop to set the "base" size for the componentonChange prop to allow validation/restriction of user input as they typedata if user hasn't actually changed a value (prevents Undo from being unnecessarily triggered)wrapperElement propid propindex in Filter (and other) function inputdefaultValue prop