# JSON 데이터 수정하기 w/ format: table

**URL:** <https://ask.selectfromuser.com/t/json-w-format-table/320>\
**Category:** 사용 팁\
**Tags:** json, format:table\
**Created:** [11월 26, 2024, 8:00오전 UTC](https://ask.selectfromuser.com/t/json-w-format-table/320 "2024-11-26T08:00:54Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![hbkim](https://yyz2.discourse-cdn.com/flex032/user_avatar/ask.selectfromuser.com/hbkim/32/23_2.png) [@hbkim](https://ask.selectfromuser.com/u/hbkim)\
**Post date:** [11월 26, 2024, 8:00오전 UTC](https://ask.selectfromuser.com/t/json-w-format-table/320/1 "2024-11-26T08:00:54Z")

</div>

format: table을 통해 JSON 형태의 데이터를 수정하는 UI 화면을 구성하는 방법을 안내드립니다.

## 핵심

- **`format: table`** : 데이터를 테이블 UI로 표시 및 입력.
- **`headers`** : 테이블 열의 입력값 형식, 유효성, 표시방식을 설정.
- **`requestFn`** : 입력 데이터를 서버에 보낼 JSON 형식으로 가공하고, 금액 범위 중복 검사를 수행.

### 예제 이미지와 YAML

 ![image](https://canada1.discourse-cdn.com/flex032/uploads/selectfromuser/original/1X/193a75540cf052dedb9eada4e427edbbb1650481.png)

 ![image](https://canada1.discourse-cdn.com/flex032/uploads/selectfromuser/original/1X/ac6f7b009588bc802bd5d884875ebc52ddcc01d0.png)

```yaml
menus:
- path: pages/sOCGir
  name: format table
pages:
- path: pages/sOCGir
  title: d=65 wine_stock의 property_json.shippingRules[] 를 수정합니다.
  blocks:
    - type: query
      resource: mysql.qa
      sqlType: update
      sql: |
        UPDATE wine_stock 
        SET property_data = :shippingRules
        where id = 65
      params:
        - key: shippingRules
          label: 배송비 규정
          format: table
          style:
            width: 700px
          showHeaders: false
          class: table text-xs
          headers:
            minAmount:
              label: 배송비시작
              format: number
              required: true
              postfix: 원 이상
              postfixStyle:
                width: 50px
            maxAmount:
              prefix: "~"
              format: number
              postfix: 원 미만
              postfixStyle:
                width: 50px
              placeholder: 비어있으면 최대금액
            shippingCost:
              format: number
              postfix: 원          
          value: # 기본값이 필요한 경우에 입력 (예제 데이터)
            - minAmount: 
                value: 0
              maxAmount: 
                value: 50000
              shippingCost: 
                value: 3000
            - minAmount: 
                value: 5000
              maxAmount: 
                value: ""
                placeholder: (최대)
              shippingCost: 
                value: 0
      reloadAfterSubmit: true
      
      requestFn: |
        const shippingRules = params.find(e => e.key == 'shippingRules')

        shippingRules.value = JSON.stringify({ 
          shippingRules: shippingRules.value.map(row => {
            return {
              minAmount: row.minAmount.value,
              maxAmount: row.maxAmount.value,
              shippingCost: row.shippingCost.value,
            }
          })
        })
      
    - type: query
      resource: mysql.qa
      title: id=65 wine_stock의 property_json의 일부분을 수정
      sqlType: select
      sql: |
        select id, property_data from wine_stock 
        where id = 65
      display: form
      responseFn: |
        rows = rows.map(e => {
          e.shippingRules = (e.property_data || {}).shippingRules || []
          e.shippingRules = e.shippingRules.map(row => {
            for (const key in row) {
              row[key] = { value: row[key] }
            }
            return row
          })
          return e
        })

        return rows
      columns:
        property_data:
          hidden: true
        shippingRules:
          label: 배송비 규정
          updateOptions:
            type: query
            resource: mysql.qa
            sqlType: update
            sql: |
              UPDATE wine_stock 
              SET property_data = :value
              where id = :id

            requestFn: |
              const value = params.find(e => e.key == 'value')
              const shippingRules = params.find(e => e.key == 'shippingRules')
              // console.log('>>>>>>', {value, params})

              function validateShippingRules(rules) {
                const errors = [];

                for (let i = 0; i < rules.length; i++) {
                  const currentRule = rules[i];
                  for (let j = i + 1; j < rules.length; j++) {
                    const nextRule = rules[j];

                    // 겹치는 조건: 두 범위가 서로 교차하는 경우
                    const isOverlapping =
                      (currentRule.maxAmount.value === null || nextRule.minAmount.value < currentRule.maxAmount.value) &&
                      (nextRule.maxAmount.value === null || currentRule.minAmount.value < nextRule.maxAmount.value);

                    if (isOverlapping) {
                      errors.push(`Overlap detected between rule ${i + 1} and rule ${j + 1}`);
                    }
                  }
                }

                return errors.length > 0 ? errors : "No overlaps detected.";
              }
              const errors = validateShippingRules(shippingRules.value)
              if (errors != "No overlaps detected.") {
                throw new Error(['금액범위를 확인해주세요.', ...errors].join('<br />'))
              }

              value.value = JSON.stringify({ 
                shippingRules: shippingRules.value.map(row => {
                  return {
                    minAmount: row.minAmount.value,
                    maxAmount: row.maxAmount.value,
                    shippingCost: row.shippingCost.value,
                  }
                })
              })

          format: table
          style:
            width: 700px
          class: table text-xs
          headers:
            minAmount:
              label: 배송비시작
              format: number
              postfix: 원 이상
              postfixStyle:
                width: 50px
            maxAmount:
              label: 금액 (없으면 최대)
              prefix: "~"
              format: number
              postfix: 원 미만
              postfixStyle:
                width: 50px
              placeholder: 비어있으면 최대금액
            shippingCost:
              label: 배송비부과
              format: number
              postfix: 원                 

```

* * *

## `format: table`

- 테이블 형식으로 데이터를 표시하거나 입력받기 위한 설정입니다.
- 사용자가 **행(row) 기반**으로 데이터를 직관적으로 관리할 수 있도록 UI를 생성합니다.
- 관련 스타일:
  - `width: 700px`: 테이블 너비 설정.
  - `showHeaders`: 테이블 헤더 표시여부
  - `class: table text-xs`: 테이블의 클래스 지정(작은 글자 크기).

## `headers`

- 테이블 열(컬럼)별 속성을 정의합니다.
- 각 열의 데이터 형식, 입력 유효성, 표시 형식을 세부적으로 지정합니다.
- `label`, `format`: 헤더 컬럼 라벨, 포맷
- `prefix`, `postfix`: 입력 필드 전후 텍스트
- `postfixStyle`: postfix 스타일

## `requestFn`

- 사용자가 입력한 테이블 데이터를 **데이터베이스 업데이트** 에 적합한 형식으로 변환하는 로직입니다.
- 주로 입력 데이터를 JSON 형태로 가공하거나 유효성 검사를 수행합니다.

### 주요 역할:

- **데이터 가공:**

- **유효성 검사:**

### 처리 예제 일부:

자세한 내용은 상단 YAML 전체 예제를 참고해주세요.

```javascript
const shippingRules = params.find(e => e.key == 'shippingRules');

// JSON 직렬화
shippingRules.value = JSON.stringify({
  shippingRules: shippingRules.value.map(row => {
    return {
      minAmount: row.minAmount.value,
      maxAmount: row.maxAmount.value,
      shippingCost: row.shippingCost.value,
    };
  }),
});

// 금액 범위 유효성 검사
function validateShippingRules(rules) { ... }

```

관련하여 도움이 필요하시면 댓글 등으로 문의주시면 안내드리겠습니다.  
감사합니다.
