如何编码和解析/解码嵌套查询字符串 Javascript

How to encode and parse / decode a nested query string Javascript

我正在通过他们的提交创建函数将表单数据从 React Hook Form 发送到 Netlify。我对单个表单字段值的编码没有任何问题,但现在我正在尝试对对象数组进行编码。

这是我的表单数据的示例:

{
  _id: "12345-67890-asdf-qwer",
  language: "Spanish",
  formId: "add-registration-form",
  got-ya: "",
  classType: "Private lessons",
  size: "1",
  days: [
    {
      day: "Monday",
      start: 08:00",
      end: "09:30"
    },
    {
      day: "Wednesday",
      start: "08:00",
      end: "09:30"
    }
  ]
}

我遇到的唯一问题是“天数”数组。我已经尝试过各种方法对此进行编码,这是我目前一直在使用的功能(这并不理想):

 const encode = (data) => {
    return Object.keys(data).map(key => {
      let val = data[key]
      if (val !== null && typeof val === 'object') val = encode(val)
      return `${key}=${encodeURIComponent(`${val}`.replace(/\s/g, '_'))}`
    }).join('&')
  }

我尝试使用像 qs 这样的库来对数据进行字符串化,但我不知道该怎么做。

这里是将数据发布到 Netlify 的函数:

// Handles the post process to Netlify so I can access their serverless functions
   const handlePost = (formData, event) => {
    event.preventDefault()
    fetch(`/`, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": 'add-registration-form', ...formData }),
    })
      .then((response) => {
        if(response.status === 200) {
          navigate("../../")
        } else {
          alert("ERROR!")
        }
        console.log(response)
      })
      .catch((error) => {
        setFormStatus("error")
        console.log(error)
      })
  }

最后,这是我提交创建的用于接收和解析编码数据的文件示例:

const sanityClient = require("@sanity/client")
const client = sanityClient({
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  dataset: process.env.GATSBY_SANITY_DATASET,
  token: process.env.SANITY_FORM_SUBMIT_TOKEN,
  useCDN: false,
})

const { nanoid } = require('nanoid');

exports.handler = async function (event, context, callback) {
  
  // Pulling out the payload from the body
  const { payload } = JSON.parse(event.body)

  // Checking which form has been submitted
  const isAddRegistrationForm = payload.data.formId === "add-registration-form"

  // Build the document JSON and submit it to SANITY
  if (isAddRegistrationForm) {


    // How do I decode the "days" data from payload?
    let schedule = payload.data.days.map(d => (
    {
      _key: nanoid(),
      _type: "classDayTime",
      day: d.day,
      time: {
        _type: "timeRange",
        start: d.start,
        end: d.end
      }
    }
  ))


    const addRegistrationForm = {
      _type: "addRegistrationForm",
      _studentId: payload.data._id,
      classType: payload.data.classType,
      schedule: schedule,
      language: payload.data.language,
      classSize: payload.data.size,
    }
    const result = await client.create(addRegistrationForm).catch((err) => console.log(err))
  }
  
  callback(null, {
    statusCode: 200,
  })
}

那么,在将表单数据发送到 Netlify 之前,如何使用嵌套的对象数组对表单数据进行正确编码?然后在 Netlify 函数中,我如何解析/解码该数据以便能够将其提交给 Sanity?

所以,qs库终究是我的救星。我只是之前没有正确实施它。因此,使用相同的表单数据结构,只需确保将 qs 导入到您的表单组件文件中即可:

import qs from 'qs'

然后使您的编码功能简洁明了:

     // Transforms the form data from the React Hook Form output to a format Netlify can read
      const encode = (data) => {
        return qs.stringify(data)
      } 

接下来,在表单的句柄提交函数中使用此编码函数:

 // Handles the post process to Netlify so we can access their serverless functions
   const handlePost = (formData, event) => {
    event.preventDefault()

    fetch(`/`, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": 'add-registration-form', ...formData }),
    })
      .then((response) => {
        reset()
        if(response.status === 200) {
          alert("SUCCESS!")
        } else {
          alert("ERROR!")
        }
        console.log(response)
      })
      .catch((error) => {
        console.log(error)
      })
  }

最后,这是您的 Netlify 提交-created.js 文件应该大致如下所示:

const sanityClient = require("@sanity/client")
const client = sanityClient({
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  dataset: process.env.GATSBY_SANITY_DATASET,
  token: process.env.SANITY_FORM_SUBMIT_TOKEN,
  useCDN: false,
}) 
const qs = require('qs')
const { nanoid } = require('nanoid');

exports.handler = async function (event, context, callback) {
  
  // Pulling out the payload from the body
  const { payload } = JSON.parse(event.body)


  // Checking which form has been submitted
  const isAddRegistrationForm = payload.data.formId === "add-registration-form"

  // Build the document JSON and submit it to SANITY
  if (isAddRegistrationForm) {
    const parsedData = qs.parse(payload.data)
    
    let schedule = parsedData.days
      .map(d => (
        {
          _key: nanoid(),
          _type: "classDayTime",
          day: d.day,
          time: {
            _type: "timeRange",
            start: d.start,
            end: d.end
          }
        }
      ))

    const addRegistrationForm = {
      _type: "addRegistrationForm",
      submitDate: new Date().toISOString(),
      _studentId: parsedData._id,
      classType: parsedData.classType,
      schedule: schedule,
      language: parsedData.language,
      classSize: parsedData.size,
    }
    const result = await client.create(addRegistrationForm).catch((err) => console.log(err))
  }
  
  callback(null, {
    statusCode: 200,
  })
}