react-jsonschema-formに含まれる、データを変換する系のユーティリティ関数を使ってみた

これは「react-jsonschema-formのカレンダー | Advent Calendar 2023 - Qiita」の19日目の記事です。

react-jsonschema-form (RJSF) にはいくつかのユーティリティ的な関数が含まれています。
RJSF utility functions, constants and types | react-jsonschema-form

それらの関数は、大きく分けると

  • Non-Validator utility functions
  • Validator-based utility functions
  • Schema utils creation function

の種類があります。

今回は Non-Validator utility functions のうち、主にデータを変換する系のユーティリティ関数を見ていきます。

 
目次

 

環境

  • react-jsonschema-form 5.15.0
  • React 18.2.0
  • React Router 6.20.1

 
なお、今回は

  • string型で日付フォーマットの入力項目
  • integer型の入力項目
  • string型の入力項目(フォーマット指定なし)

を持ったフォームの onSubmit の「ここに追加する」の場所にて、調査対象の関数を実行し挙動を確認します。

import {asNumber, guessType, localToUTC, pad, parseDateString, RJSFSchema, toDateString, utcToLocal} from "@rjsf/utils";
import Form from "@rjsf/mui";  // MUI version
import validator from "@rjsf/validator-ajv8";

export const TransformationFunctionForm = () => {
  const schema: RJSFSchema = {
    title: "Transformation Function",
    type: "object",
    properties: {
      datetimeInput: {
        type: "string",
        format: "date-time",
        default: "2023-12-19 00:00:00"
      },
      integerInput: {
        type: "integer"
      },
      stringInput: {
        type: "string"
      }
    }
  }

  // onSubmitの引数の説明は以下
  // https://rjsf-team.github.io/react-jsonschema-form/docs/api-reference/form-props#onsubmit
  const onSubmit = ({formData}, _event) => {
    console.log(formData)

    // ここに追加する
  }

  return (
    <div style={{width: '400px'}}>
      <Form
        schema={schema}
        validator={validator}
        onSubmit={onSubmit}
      />
    </div>
  )
}

 

データの型を推測する guessType()

データの型を推測する場合、 typeof だったり、オブジェクトの [[Class]] を用いた判定だったりが使えます。
JavaScriptの「型」の判定について #JavaScript - Qiita

また、RJSFの場合は guessType() 関数も使えます。
guessType() | RJSF utility functions, constants and types | react-jsonschema-form

そこで、 [[Class]]guessType() ではどのように違うのかをためしてみます。

まず [[Class]] の結果は以下の通りでした。

const toString = Object.prototype.toString

console.log(toString.call(formData.datetimeInput))  // => [object String]
console.log(toString.call(formData.integerInput))   // => [object Number]
console.log(toString.call(new Date()))              // => [object Date]

 
一方、guessType の結果は以下の通りでした。

Date オブジェクトの場合はnumber型とみなしたようです。JSON Schemaには日付がないことから、これでも問題ないのかもしれません。

console.log(guessType(formData.datetimeInput)) // => string
console.log(guessType(formData.integerInput))  // => number
console.log(guessType(new Date()))             // => number

 

文字列を DateObject へと変換する parseDateString()

RJSFで type="string" かつ format="date-time" の場合、見た目が日時の入力になります。

 
また、 formData で受け取ったときの値は文字列になります。

const toString = Object.prototype.toString
console.log(toString.call(formData.datetimeInput))
// => [object String]

 
そのため、入力値を日付として扱いたい場合、 parseDateString() 関数を使うと便利です。
parseDateString() | RJSF utility functions, constants and types | react-jsonschema-form

なお、この関数の戻り値は DateObject 型であり、JavaScriptDate とは異なります。

ためしに型を判定させてみると、Date ではなく Object になります。

console.log(toString.call(new Date()))
// => [object Date]

console.log(toString.call(parseDateString(formData.datetimeInput, true)))
// => [[object Object]]

 
なお、第2引数の includeTime に boolean を渡すことで、時刻の設定有無を変更します。

console.log(parseDateString(formData.datetimeInput, false)) // 時刻なし
console.log(parseDateString(formData.datetimeInput, true))  // 時刻あり

 
変換後の値をコンソールで確認すると以下の結果になりました。

 

DateObject を文字列にする toDateString()

parseDateString と逆の動きをするのが toDateString 関数です。
toDateString() | RJSF utility functions, constants and types | react-jsonschema-form

こちらも第2引数 time に boolean を渡すことで、時刻を含む・含まないの切り替えができます。

const dateObject = parseDateString(formData.datetimeInput, true)

console.log(toDateString(dateObject, false)) // 時刻なし
console.log(toDateString(dateObject, true)) // 時刻あり

 
コンソールへの出力は以下でした。

 

ローカル時刻文字列をUTC文字列にする localToUTC()

日付への変換ではなく、ローカル時刻からUTCへと文字列のまま変換するのが localToUTC() 関数です。
RJSF utility functions, constants and types | react-jsonschema-form

なお、この関数の引数は元となる日時の文字列だけであり、タイムゾーンなどは渡せません。

console.log(formData.datetimeInput)
// => 2023-12-19 00:00:00

console.log(localToUTC(formData.datetimeInput))
// => 2023-12-18T15:00:00.000Z

 

UTC文字列をローカル時刻文字列にする utcToLocal()

localToUTC とは逆の関数が utcToLocal になります。
utcToLocal() | RJSF utility functions, constants and types | react-jsonschema-form

なお、 utcToLocal 関数も引数としてタイムゾーンを受け取ることができません。

また、フォームから入力したデータをそのまま渡すと変換できず、末尾にUTCを表す Z が必要です。

console.log(utcToLocal(formData.datetimeInput))
// => 2023-12-19T00:00:00.000

connsole.log(utcToLocal(`${formData.datetimeInput}Z`))  // 末尾に "Z" を付与してUTC化
// => 2023-12-19T09:00:00.000

 

先頭ゼロ詰めする pad()

入力値に対して先頭ゼロ詰めしたい場合は pad() 関数が使えます。
pad() | RJSF utility functions, constants and types | react-jsonschema-form

pad 関数の桁数に届かない場合はゼロ詰めを、超過したり undefined を渡すとそのまま返ってきます。

console.log(pad(formData.integerInput, 4))
// 3を入力 => 0003
// 30000を入力 => 30000
// undefinedのまま => undefined

 

数値化する関数 asNumber()

入力値に応じて数値化する関数 asNumber() もあります。
asNumber() | RJSF utility functions, constants and types | react-jsonschema-form

.11.1.2 を渡した時のそれぞれの挙動を見てみます。

console.log(asNumber(formData.stringInput))
// .1 を入力 => 0.1
// 1. を入力 => 1.
// 1.2 を入力 => 1.2

 

ソースコード

Githubにあげました。
https://github.com/thinkAmi-sandbox/rjsf_advent_calendar_2023

今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/rjsf_advent_calendar_2023/pull/17