使用AJAX读取PLC类JSON格式HTML文件时遇'unexpected token'错误的解决
问题描述
我有一台西门子S7-1200 PLC,其内置网页api.htm格式类似JSON但实际为HTML(因PLC修改变量必须采用HTML格式)。尝试通过外部Web服务器的AJAX请求读取该网页内容时,仅设置dataType: 'jsonp'可实现跨域,但请求触发报错:Uncaught SyntaxError: unexpected token: ':'(位于api.htm第2行第9位)。推测原因是请求预期JSON格式,但实际获取的是不符合JSON规范的HTML内容。
附api.htm内容
{ "Muntje"::="Feedback-WS".Muntje:, "AdK"::="Feedback-WS".Aanraking_der_Kunst:, "Juwelenkistje"::="Feedback-WS".Juwelenkistje:, "Duivelsbeeld"::="Feedback-WS".Duivelsbeeld:, "Klok"::="Feedback-WS".Klok:, "Hertenpoot"::="Feedback-WS".Hertenpoot:, "Zekering_Kledingkast"::="Feedback-WS".Zekering_Kledingkast:, "Bed_knop_1"::="Feedback-WS".Bed_knop_1:, "Bed_knop_2"::="Feedback-WS".Bed_knop_2:, "Bed_knop_3"::="Feedback-WS".Bed_knop_3:, "Bed_knop_4"::="Feedback-WS".Bed_knop_4:, "Vacuum_Pomp"::="Feedback-WS".Vacuum_Pomp:, "Signaal_Generator"::="Feedback-WS".Signaal_Generator:, "Stekkerrek"::="Feedback-WS".Stekkerrek:, "Zekering_1"::="Feedback-WS".Zekering_1:, "Zekering_2"::="Feedback-WS".Zekering_2:, "Zekering_3"::="Feedback-WS".Zekering_3:, "Hoofdschakelaar"::="Feedback-WS".Hoofdschakelaar:, "Morse_Code"::="Feedback-WS".Morse_Code: }
AJAX请求代码
var settings = { 'cache': false, 'dataType': "jsonp", "contentType": "application/json; charset=utf-8", "async": true, "crossDomain": true, "url": "http://192.168.22.160/awp/TIR/api.htm", "method": "GET", "headers": { "accept": "application/json", "Access-Control-Allow-Origin":"*" } } $.ajax(settings).done(function (response) { //console.log($.parseJSON(response)); });
解决方案
1. 修正api.htm格式为标准JSON
当前api.htm内容不符合JSON规范:
- 键值对分隔符用了
::=,而非JSON要求的: - 值的末尾多余冒号,且格式不是合法的JSON值类型
若PLC允许修改api.htm输出,调整为标准JSON格式:
{ "Muntje": "Feedback-WS.Muntje", "AdK": "Feedback-WS.Aanraking_der_Kunst", "Juwelenkistje": "Feedback-WS.Juwelenkistje", "Duivelsbeeld": "Feedback-WS.Duivelsbeeld", "Klok": "Feedback-WS.Klok", "Hertenpoot": "Feedback-WS.Hertenpoot", "Zekering_Kledingkast": "Feedback-WS.Zekering_Kledingkast", "Bed_knop_1": "Feedback-WS.Bed_knop_1", "Bed_knop_2": "Feedback-WS.Bed_knop_2", "Bed_knop_3": "Feedback-WS.Bed_knop_3", "Bed_knop_4": "Feedback-WS.Bed_knop_4", "Vacuum_Pomp": "Feedback-WS.Vacuum_Pomp", "Signaal_Generator": "Feedback-WS.Signaal_Generator", "Stekkerrek": "Feedback-WS.Stekkerrek", "Zekering_1": "Feedback-WS.Zekering_1", "Zekering_2": "Feedback-WS.Zekering_2", "Zekering_3": "Feedback-WS.Zekering_3", "Hoofdschakelaar": "Feedback-WS.Hoofdschakelaar", "Morse_Code": "Feedback-WS.Morse_Code" }
修改后可直接使用dataType: 'json'(若跨域问题已解决)或保持jsonp(需PLC支持JSONP回调)。
2. 获取原始文本后手动解析
若PLC无法修改api.htm格式,改用dataType: 'text'获取原始内容,再手动处理成合法JSON:
var settings = { 'cache': false, 'dataType': "text", // 改为获取纯文本 "async": true, "crossDomain": true, "url": "http://192.168.22.160/awp/TIR/api.htm", "method": "GET" } $.ajax(settings).done(function (response) { // 替换不符合JSON的语法 let processedStr = response .replace(/::=/g, ':') // 把::=替换为标准JSON键值分隔符: .replace(/:"([^"]+)":/g, ':"$1"'); // 移除值末尾的冒号 try { var plcData = JSON.parse(processedStr); console.log('解析后数据:', plcData); // 后续业务逻辑处理 } catch (parseErr) { console.error('解析失败:', parseErr); } });
3. 解决跨域限制
如果使用dataType: 'text'时出现跨域错误,可通过两种方式处理:
- PLC端配置:在西门子S7-1200的Web服务器设置中,添加
Access-Control-Allow-Origin响应头,指定允许访问的外部Web服务器域名(或*允许所有域名) - 反向代理:在外部Web服务器上配置反向代理,将PLC的请求路径映射为同域路径,避免跨域校验
内容的提问来源于stack exchange,提问作者Gvmarle
相关产品推荐
相关产品推荐

