带Schema验证的JSON文件编辑功能故障排查求助
问题描述
大学项目中的地标编辑功能原本可正常从数据库读取JSON并完成编辑操作,但添加Schema验证后功能异常,且无任何错误提示,无法定位是验证逻辑问题还是其他原因导致故障。尝试多种验证方式均无效,以下是React代码及JSON数据示例:
React代码
import React, {Component} from "react" import Form from "react-bootstrap/Form" import {Redirect, Link} from "react-router-dom" import axios from "axios" import LinkInClass from "../components/LinkInClass" import {SERVER_HOST} from "../config/global_constants" export default class EditLandmark extends Component { constructor(props) { super(props) this.state = { name:``, // type:``, url:``, telephone:``, addressRegion:``, addressLocality:``, latitude:``, longitude:``, tags:``, redirectToDisplayAllLandmarks:false } } componentDidMount() { this.inputToFocus.focus() axios.get(`${SERVER_HOST}/landmarks/${this.props.match.params.id}`) .then(res => { if(res.data) { if (res.data.errorMessage) { console.log(res.data.errorMessage) } else { this.setState({ name: res.data.name, // type: res.data.type, url: res.data.url, telephone: res.data.telephone, addressRegion: res.data.address.addressRegion, addressLocality: res.data.address.addressLocality, latitude: res.data.geo.latitude, longitude: res.data.geo.longitude, tags: res.data.tags }) } } else { console.log(`Record not found`) } }) } handleChange = (e) => { this.setState({[e.target.name]: e.target.value}) } handleSubmit = (e) => { e.preventDefault() this.setState({ wasSubmittedAtLeastOnce: true }); const formInputsState = this.validate(); if (Object.keys(formInputsState).every(index => formInputsState[index])) { const landmarkObject = { name: this.state.name, // type: this.state.type, url: this.state.url, telephone: this.state.telephone, addressRegion: this.state.addressRegion, addressLocality: this.state.addressLocality, latitude: this.state.latitude, longitude: this.state.longitude, tags: this.state.tags } axios.put(`${SERVER_HOST}/landmarks/${this.props.match.params.id}`, landmarkObject) .then(res => { if(res.data) { if (res.data.errorMessage) { console.log(res.data.errorMessage) } else { console.log(`Record updated`) this.setState({redirectToDisplayAllLandmarks:true}) } } else { console.log(`Record not updated`) } }) } } validateName() { const pattern = /^[a-zA-Z]+ [a-zA-Z]+$/; return pattern.test(String(this.state.name)) } // validateType() // { // const pattern = /^[A-Za-z]+$/; // return pattern.test(String(this.state.type)) // } validateUrl() { const pattern = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/; return pattern.test(String(this.state.url)) } validateTelephone() { const pattern = /^[\+]?[(]?[0-9]{[2-9]{1}\d{2}}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/; return pattern.test(String(this.state.telephone)) } validateAddressRegion() { const pattern = /^[A-Za-z]+$/; return pattern.test(String(this.state.addressRegion)) } validateAddressLocality() { const pattern = /^[a-zA-Z]+ [a-zA-Z]+$/; return pattern.test(String(this.state.addressLocality)) } validateLatitude() { const latitude = parseInt(this.state.latitude) return (latitude >= -90 && latitude <= 90) } validateLongitude() { const longitude = parseInt(this.state.longitude) return (longitude >= -180 && longitude <= 180) } validateTags() { const pattern = /^[a-zA-Z]+ [a-zA-Z]+$/; return pattern.test(String(this.state.tags)) } validate() { return { name: this.validateName(), // type: this.validateType(), url: this.validateUrl(), telephone: this.validateTelephone(), addressRegion: this.validateAddressRegion(), addressLocality: this.validateAddressLocality(), latitude: this.validateLatitude(), longitude: this.validateLongitude(), tags: this.validateTags() }; } render() { let errorMessage = ""; if(this.state.wasSubmittedAtLeastOnce) { errorMessage = <div className="error">Landmark Details are incorrect<br/></div>; } return ( <div className="form-container"> {this.state.redirectToDisplayAllLandmarks ? <Redirect to="/DisplayAllLandmarks"/> : null} <Form> {errorMessage} <Form.Group controlId="name"><Form.Label>Name</Form.Label> <Form.Control ref = {(input) => { this.inputToFocus = input }} type="text" name="name" value={this.state.name} onChange={this.handleChange} /> </Form.Group> {/* <Form.Group controlId="type"> <Form.Label>Type</Form.Label> <Form.Control type="text" name="type" value={this.state.type} onChange={this.handleChange} /> </Form.Group> */} <Form.Group controlId="url"> <Form.Label>Url</Form.Label> <Form.Control type="text" name="url" value={this.state.url} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="telephone"> <Form.Label>Telephone</Form.Label> <Form.Control type="text" name="telephone" value={this.state.telephone} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="addressRegion"> <Form.Label>AddressRegion</Form.Label> <Form.Control type="text" name="addressRegion" value={this.state.addressRegion} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="addressLocality"> <Form.Label>AddressLocality</Form.Label> <Form.Control type="text" name="addressLocality" value={this.state.addressLocality} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="latitude"> <Form.Label>Latitude</Form.Label> <Form.Control type="text" name="latitude" value={this.state.latitude} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="longitude"> <Form.Label>Longitude</Form.Label> <Form.Control type="text" name="longitude" value={this.state.longitude} onChange={this.handleChange} /> </Form.Group> <Form.Group controlId="tags"> <Form.Label>Tags</Form.Label> <Form.Control type="text" name="tags" value={this.state.tags} onChange={this.handleChange} /> </Form.Group> <LinkInClass value="Add" className="add-button" onClick={this.handleSubmit}/> <Link className="cancel-button" to="/DisplayAllLandmarks">Cancel</Link> </Form> </div> ) } }
JSON数据示例
{ "name": "Skryne Church", "url": "https://www.skryneandrathfeighparish.ie/", "geo": { "@type": "GeoCoordinates", "longitude": -6.5631088, "latitude": 53.5859852 }, "telephone": "+3530469025152", "address": { "@type": "PostalAddress", "addressLocality": "Dublin", "addressRegion": "Dublin", "addressCountry": "Republic of Ireland" }, "image": { "@type": "ImageObject", "caption": "Fáilte Ireland Logo", "url": "https://failtecdn.azureedge.net/failteireland/F%C3%A1ilte_Ireland_Logo_OpenDataAPI.jpg" }, "tags": ["Activity", "Church Abbey", "Monastery", "Attraction", "Churches", "Abbeys and Monastery"] }
问题排查与修复建议
1. 正则表达式错误
- 电话号码验证正则:
/^[\+]?[(]?[0-9]{[2-9]{1}\d{2}}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/语法错误,{[2-9]{1}\d{2}}写法违规,修正为:/^[\+]?[(]?[2-9]\d{2}[)]?[-\s\.]?\d{3}[-\s\.]?\d{4,6}$/ - 地址区域验证:
/^[A-Za-z]+$/不允许空格,若存在带空格的区域名会验证失败,改为/^[A-Za-z\s]+$/ - 地址Locality验证:
/^[a-zA-Z]+ [a-zA-Z]+$/强制要求两个单词,但示例数据中addressLocality是单个单词"Dublin",直接导致验证失败,需改为允许单个或多个单词:/^[a-zA-Z\s]+$/ - 标签验证:
/^[a-zA-Z]+ [a-zA-Z]+$/无法匹配数组格式的tags,需针对数组元素做验证
2. 数值类型处理错误
- 经纬度验证:
parseInt()会丢失小数精度,且未判断是否为有效数字,修正为:
validateLatitude() { const latitude = parseFloat(this.state.latitude) return !isNaN(latitude) && latitude >= -90 && latitude <= 90 } validateLongitude() { const longitude = parseFloat(this.state.longitude) return !isNaN(longitude) && longitude >= -180 && longitude <= 180 }
3. 提交数据结构不匹配
后端JSON中address、geo是嵌套对象,但当前提交的是扁平字段,需组装成对应结构:
const landmarkObject = { name: this.state.name, url: this.state.url, telephone: this.state.telephone, address: { addressRegion: this.state.addressRegion, addressLocality: this.state.addressLocality }, geo: { latitude: this.state.latitude, longitude: this.state.longitude }, tags: this.state.tags }
4. Tags字段处理错误
示例中tags是数组,但表单输入为字符串,需转换格式:
// 处理tags输入转换 handleChange = (e) => { const { name, value } = e.target; if (name === 'tags') { this.setState({ [name]: value.split(',').map(tag => tag.trim()) }); } else { this.setState({ [name]: value }); } } // 验证数组每个元素 validateTags() { if (!Array.isArray(this.state.tags) || this.state.tags.length === 0) return false; const pattern = /^[a-zA-Z\s]+$/; return this.state.tags.every(tag => pattern.test(tag)); }
5. 验证反馈缺失
全局错误提示无法定位具体问题字段,建议给每个字段添加单独错误提示:
<Form.Group controlId="name"> <Form.Label>Name</Form.Label> <Form.Control ref={(input) => { this.inputToFocus = input }} type="text" name="name" value={this.state.name} onChange={this.handleChange} /> {this.state.wasSubmittedAtLeastOnce && !this.validateName() && <span className="field-error">名称需为英文单词组合</span>} </Form.Group>
内容的提问来源于stack exchange,提问作者N.L. MAT
相关产品推荐
相关产品推荐

