You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:25:21