Skip to content

redgoose-dev/json-editor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

JSON Editor

"json-editor"๋Š” ์›น๋ธŒ๋ผ์šฐ์ €์—์„œ json ๋ฐ์ดํ„ฐ๋ฅผ ํŽธ์ง‘ํ•˜๋Š” ์—๋””ํ„ฐ์ž…๋‹ˆ๋‹ค.
ํ…์ŠคํŠธ ํŽธ์ง‘ํˆด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ json ๋ฐ์ดํ„ฐ๋ฅผ ์†์‰ฝ๊ฒŒ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•˜์—ฌ ๋งŒ๋“ค์–ด์ง„ ํ”„๋กœ๊ทธ๋žจ ์ž…๋‹ˆ๋‹ค. ์ด ์—๋””ํ„ฐ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์—๋””ํ„ฐ์˜ ๊ธฐ๋Šฅ์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ถŒ์žฅ๋˜๋Š” ์‚ฌ์šฉํ™˜๊ฒฝ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋ฐ์Šคํฌํƒ‘
  • ํฐ ํ™”๋ฉด์˜ ํƒœ๋ธ”๋ฆฟ

์—๋””ํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ๋ฐ๋ชจ๋ฅผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ๋ชจํŽ˜์ด์ง€์—์„œ ์ž„์‹œ๋กœ ์—๋””ํ„ฐ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ๋ชจ๋งํฌ: https://redgoose-dev.github.io/json-editor/

Using

javascript์™€ css๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

import JsonEditor from '@redgoose/json-editor'
import '@redgoose/json-editor/css'

const jsonEditor = new JsonEditor(document.getElementById('target'), {
  live: true,
  theme: 'system',
  edit: 'all',
  node: {},
  openDepth: 2,
})

Options

์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ• ๋•Œ์— ์‚ฌ์šฉํ•˜๋Š” ์˜ต์…˜๊ฐ’์ž…๋‹ˆ๋‹ค.

  • live / (true,false)
    ์ด ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋ ๋•Œ๋งˆ๋‹ค update ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ์—…๋ฐ์ดํŠธ ์ด๋ฒคํŠธ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • theme / (system,light,dark)
    ๋‹คํฌ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ฐ’์ž…๋‹ˆ๋‹ค.
  • edit / (all,value,none)
    ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„๋ฅผ ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • node / ({},[])
    ํด๋ž˜์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ• ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋…ธ๋“œ ๋ฐ์ดํ„ฐ ๊ฐ’์ž…๋‹ˆ๋‹ค.
  • openDepth / 0
    x๋ฒˆ์งธ ๋ށ์Šค์˜ ๋…ธ๋“œ๊ฐ€ ์—ด๋ฆฌ๋Š”์ง€์— ๋Œ€ํ•˜์—ฌ ์ •ํ•ฉ๋‹ˆ๋‹ค.

Methods

์ธ์Šคํ„ด์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋“ค์ด๋ฉฐ ํ•„์š”ํ• ๋•Œ์— ์ ์ ˆํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•„๋‹ˆ๋ฉด ํด๋ž˜์Šค ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๋ฏธ๋ฆฌ ํ™•์žฅํ•ด๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)
์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ps. ๋จผ์ € ์†Œ์Šค์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

const jsonEditor = new JsonEditor()
const node = document.querySelector('.node') // node

addNode

object, array ๋…ธ๋“œ์—์„œ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.addNode(node, data, options, useUpdate, useUpdateCount)
  • node: ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • data: ์ถ”๊ฐ€ํ•  ๋ฐ์ดํ„ฐ
  • options: ์ถ”๊ฐ€์˜ต์…˜
  • useUpdate: ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • useUpdateCount: ๋ถ€๋ชจ๋…ธ๋“œ ๋ฐ์ดํ„ฐ ๊ฐฏ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.addNode(
  node,
  { key: '', type: 'string', value: 'metal' },
  options,
  true,
  true
)

removeNode

๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.removeNode(node, useUpdate)
  • node: ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • useUpdate: ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.removeNode(node, true)

changeType

๋…ธ๋“œ์˜ ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.changeType(node, type, useUpdate)
  • node: ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • type: ํƒ€์ž…์˜ ์ด๋ฆ„ (object,array,string,number,boolean,null)
  • useUpdate: ๋…ธ๋“œ ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.changeType(node, 'boolean', true)

changeKey

๋…ธ๋“œ์˜ key๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.changeKey(node, keyword)
  • node: ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • keyword: ํ‚ค์›Œ๋“œ

changeValue

๋…ธ๋“œ์˜ value๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.changeValue(node, value)
  • node: ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • value: ๊ฐ’

duplicate

๋…ธ๋“œ๋ฅผ ๋ณต์ œํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.duplicate(node, useUpdate)
  • node: ๋ณต์ œํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • useUpdate: ์‹คํ–‰ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.duplicate(node, true)

fold

๋…ธ๋“œ๋ฅผ ์ ‘๊ฑฐ๋‚˜ ํŽผ์นฉ๋‹ˆ๋‹ค.

jsonEditor.fold(node, true)

import

๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

jsonEditor.import(node, data, useUpdate, useUpdateCount)
  • node: ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • data: ๊ฐ€์ ธ์˜ฌ ๋ฐ์ดํ„ฐ
  • useUpdate: ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • useUpdateCount: ๋ถ€๋ชจ๋…ธ๋“œ ๋ฐ์ดํ„ฐ ๊ฐฏ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.import(node, { foo: 'bar' }, true, true)

replace

๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.replace(data, options, useUpdate)
  • data: ์ƒˆ๋กœ ๊ต์ฒดํ•  ๋ฐ์ดํ„ฐ
  • options: ์˜ต์…˜
    • openDepth: ๋ฐ์ดํ„ฐ๊ฐ€ ๊ต์ฒด๋ ๋•Œ ๋…ธ๋“œ๊ฐ€ ์—ด๋ฆฌ๋Š” x๋ฒˆ์งธ ๋ށ์Šค
  • useUpdate: ๋…ธ๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

jsonEditor.replace({ foo: 'bar' }, {
  openDepth: 2,
}, true)

export

์—๋””ํ„ฐ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

jsonEditor.export(node, json, space)
  • node: ๊ฐ€์ ธ์˜ฌ ๋ฐ์ดํ„ฐ์˜ ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • json: json ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์—ฌ๋ถ€
  • space: json ๊ณต๋ฐฑ

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const space = 2 // null,2,'\t'
jsonEditor.export(node, true, space)

clear

๋…ธ๋“œ์˜ ๋‚ด์šฉ์„ ๋น„์›๋‹ˆ๋‹ค.

jsonEditor.clear()

destroy

๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค๋ฅผ ํŒŒ๊ดดํ•ฉ๋‹ˆ๋‹ค.

jsonEditor.destroy()

Events

์—๋””ํ„ฐ์—์„œ ์ผ์–ด๋‚œ ์ผ๋“ค์„ ์™ธ๋ถ€์—์„œ ์ด๋ฒคํŠธ๋ฆฌ์Šค๋„ˆ๋กœ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ps. ๋จผ์ € ์†Œ์Šค์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

const jsonEditor = new JsonEditor()
const wrap = jsonEditor.el.wrap.get(0) // wrap element

update

์—๋””ํ„ฐ์˜ ๋‚ด์šฉ์ด ์ˆ˜์ •๋œ๋‹ค๋ฉด ์‹คํ–‰๋˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

wrap.addEventListener('update', ({ detail }) => {
  console.log('updated data', src)
})
  • detail: ๋ฐ์ดํ„ฐ ๊ฐ์ฒด

context

์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ์—ด๋ฆด๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋‰ด๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ œ๊ณต๋œ ํŒŒ๋ผ๋ฉ”ํ„ฐ ๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ์ƒํ™ฉ์— ๋งž๊ฒŒ ๋ฉ”๋‰ด๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

wrap.addEventListener('context', ({ detail: { body, node, type, isRoot, $ } }) => {
  if (!isRoot) return
  const $ul = $(body).children()
  const $items = $(`
    <li><button type="button" data-key="#1">custom #1</button></li>
    <li><button type="button" data-key="#2">custom #2</button></li>
  `)
  $items.find('button').on('click', (e) => {
    console.log('click item-key:', $(e.currentTarget).data('key'))
    jsonEditor.context.close()
  })
  $ul.append($items)
})
  • body: ์—ด๋ฆฐ ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด ์˜์—ญ. ์ด ์—˜๋ฆฌ๋จผํŠธ์—๋‹ค ํ•ญ๋ชฉ์„ ์กฐ์ž‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • node: ์„ ํƒ๋œ ๋…ธ๋“œ ์—˜๋ฆฌ๋จผํŠธ
  • type: ์„ ํƒ๋œ ๋…ธ๋“œ์˜ ํƒ€์ž…
  • isRoot: ํ˜„์žฌ ์„ ํƒ๋œ ๋…ธ๋“œ๊ฐ€ ๋ฃจํŠธ์ธ์ง€ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฐ’
  • $: ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” Cash๋ฅผ ์ด์šฉํ•˜์—ฌ ์†์‰ฝ๊ฒŒ dom์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Exports guide

๋‹ค์Œ ๊ฒฝ๋กœ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๋ชจ๋“ˆ๋“ค์„ import ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๋Š”๋ฐ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • @redgoose/json-editor: ์ฝ”์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • @redgoose/json-editor/css: ์Šคํƒ€์ผ์‹œํŠธ
  • @redgoose/json-editor/lib/umd: ์ฝ”์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ UMD

Custom style

์—๋””ํ„ฐ์˜ ๋””์ž์ธ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋“ค์„ ๋ณ€์ˆ˜ํ™” ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์ด ์™ธ๋ถ€ ์˜์—ญ์—์„œ ์—๋””ํ„ฐ ์Šคํƒ€์ผ์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

.editor {
  --json-editor-color-base: red;
  --json-editor-color-focus: blue;
}
@media (prefers-color-scheme: dark) {
  .editor {
    --json-editor-color-base: green;
    --json-editor-color-focus: yellow;
  }
}

main.scss ํŒŒ์ผ์˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ง์ ‘ ์Šคํƒ€์ผ์„ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Extention language

ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ๊ต์ฒดํ•˜์—ฌ ์—๋””ํ„ฐ ํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JsonEditor.prototype.updateLanguage = function()
{
  this.lang = Object.assign(this.lang, {
    nodeChangeSort: '๋…ธ๋“œ ์ˆœ์„œ๋ณ€๊ฒฝ',
    nodeContextMenu: '๋…ธ๋“œ๋ฉ”๋‰ด',
    nodeFold: '์ ‘๊ธฐ/ํŽผ์น˜๊ธฐ',
    contextChangeType: 'ํƒ€์ž…๋ณ€๊ฒฝ',
    contextInsertNode: '๋…ธ๋“œ์ถ”๊ฐ€',
    contextTypeObject: '๊ฐ์ฒด',
    contextTypeArray: '๋ฐฐ์—ด',
    contextTypeString: '๋ฌธ์ž',
    contextTypeNumber: '๋ฒˆํ˜ธ',
    contextTypeBoolean: '๋ถ€์šธ',
    contextTypeNull: '๋„',
    contextDuplicate: '๋…ธ๋“œ๋ณต์ œ',
    contextRemove: '๋…ธ๋“œ์‚ญ์ œ',
  })
}

Developing a wrapper

JSON Editor ์—๋””ํ„ฐ๋ฅผ web component, react, vue, svelte ๊ฐ™์€ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.