一个AJAX调用返回了一个包含JSON字符串的响应文本。我需要:
- 提取JSON字符串
- 修改它
- 然后重新插入以更新原始字符串
我不太担心步骤2和3,但我无法想出如何执行步骤1。我考虑使用正则表达式,但是由于我的JSON可能具有多个级别的嵌套对象或数组,所以不知道该如何操作。
一个AJAX调用返回了一个包含JSON字符串的响应文本。我需要:
我不太担心步骤2和3,但我无法想出如何执行步骤1。我考虑使用正则表达式,但是由于我的JSON可能具有多个级别的嵌套对象或数组,所以不知道该如何操作。
{
或[
)和最后一个结尾(}
或]
)括号。JSON.parse()
解析该文本块(包括括号)。如果成功,完成并返回解析结果。function extractJSON(str) {
var firstOpen, firstClose, candidate;
firstOpen = str.indexOf('{', firstOpen + 1);
do {
firstClose = str.lastIndexOf('}');
console.log('firstOpen: ' + firstOpen, 'firstClose: ' + firstClose);
if(firstClose <= firstOpen) {
return null;
}
do {
candidate = str.substring(firstOpen, firstClose + 1);
console.log('candidate: ' + candidate);
try {
var res = JSON.parse(candidate);
console.log('...found');
return [res, firstOpen, firstClose + 1];
}
catch(e) {
console.log('...failed');
}
firstClose = str.substr(0, firstClose).lastIndexOf('}');
} while(firstClose > firstOpen);
firstOpen = str.indexOf('{', firstOpen + 1);
} while(firstOpen != -1);
}
var obj = {'foo': 'bar', xxx: '} me[ow]'};
var str = 'blah blah { not {json but here is json: ' + JSON.stringify(obj) + ' and here we have stuff that is } really } not ] json }} at all';
var result = extractJSON(str);
console.log('extracted object:', result[0]);
console.log('expected object :', obj);
console.log('did it work ?', JSON.stringify(result[0]) == JSON.stringify(obj) ? 'yes!' : 'no');
console.log('surrounding str :', str.substr(0, result[1]) + '<JSON>' + str.substr(result[2]));
示例(在Node.js环境下执行,但也应适用于浏览器):https://paste.aeum.net/show/81/
如果您想从文本中提取JSON字符串(即使它们不是有效的),您可以查看这个Gulp插件https://www.npmjs.com/package/gulp-extract-json-like。它会搜索所有看起来像JSON字符串格式的字符串。
创建一个文件夹并安装包。
mkdir project && cd project
npm install gulp gulp-extract-json-like
./gulpfile.js
,并将以下内容放入其中:var gulp = require('gulp');
var extractJsonLike = require('gulp-extract-json-like');
gulp.task('default', function () {
return gulp.src('file.txt')
.pipe(extractJsonLike())
.pipe(gulp.dest('dist'));
});
./file.txt
的文件,其中包含您的文本,并运行以下命令。gulp
./dist/file.txt
中。如果JSON作为ajax响应的一部分返回,为什么不使用浏览器本身的JSON解析(注意陷阱)?或者使用jQuery JSON解析呢?
如果JSON与文本完全混在一起,那真的让人感到设计有问题,在我看来 - 如果可以改变它,我强烈建议这样做(即将单个JSON对象作为响应返回,并将文本作为对象的属性)。
如果不能改变,那么使用正则表达式将是一场绝对的噩梦。JSON本身非常灵活,确保准确解析不仅耗时,而且浪费资源。我可能会在开头/结尾放入内容标记,并希望一切顺利。但你将面临验证错误等问题。
//PrettyPrint() will attempt to find JSON strings in the log message. If it finds them, it will replace the raw ugly JSON with pretty printted JSON
function PrettyPrint() {
var jsonStrings = [];
var prettyLogElement = document.getElementById('PrettyLogDisplayOnly');
try {
var rawLogMessage = $("textarea[id^='LogMessage']").val();
if (rawLogMessage == null) {
throw "Failed to extract original log message.";
}
jsonStrings = ExtractJsonStrings(rawLogMessage);
var modifiedLogMessage = "<pre>" + rawLogMessage + "\"</pre>";
for (const jsonString of jsonStrings) {
try {
var jsonObject = JSON.parse(jsonString);
var prettyPrintJsonString = JSON.stringify(jsonObject, null, 2);
modifiedLogMessage = modifiedLogMessage.replace(jsonString, prettyPrintJsonString);
}
catch (err) {
modifiedLogMessage += "Failed to pretty print: " + jsonString;
}
}
}
catch (err) {
if (err == null || err == undefined) {
err = "Failed to parse.";
}
else
{
err = "Failed to parse. Details: " + err;
}
//TODO: instead of showing the error here, show it as an error banner?
rawLogMessage = "<br/>Failed to beautify JSON objects. Details: " + err + " Displaying raw log message.<br/>" +
"<br/>-------------------------------------------------------------------------------------<br/><br/>"
+ rawLogMessage;;
prettyLogElement.innerHTML += rawLogMessage;
return;
}
prettyLogElement.innerHTML = modifiedLogMessage;
}
function ExtractJsonStrings(rawLogMessage) {
var jsonStrings = [];
var locationOfCurrentCurly = -1;
while (true) {
var countOfOpenCurlyBraces = 0;
var countOfClosedCurlyBraces = 0;
var locationOfFirstUnescapedOpeningCurly = GetLocationOfNextUnescapedOpeningCurlyBrace(rawLogMessage, locationOfCurrentCurly + 1);
if (locationOfFirstUnescapedOpeningCurly == -1) {
break; //we found all the JSON strings
}
else
{
locationOfCurrentCurly = locationOfFirstUnescapedOpeningCurly;
countOfOpenCurlyBraces++;
}
while (countOfOpenCurlyBraces != countOfClosedCurlyBraces)
{
if (countOfClosedCurlyBraces > countOfOpenCurlyBraces)
{
throw "Found more closing curly braces than opening curly braces.";
}
var startSearchAtIndex = locationOfCurrentCurly + 1
locationOfCurrentCurly = GetLocationOfNextUnescapedCurlyBrace(rawLogMessage, startSearchAtIndex);
if (locationOfCurrentCurly == -1) {
throw "Failed to find the 'next' curly brace.";
}
var curly = rawLogMessage.charAt(locationOfCurrentCurly);
if (curly === '{') {
countOfOpenCurlyBraces++;
} else if (curly === '}') {
countOfClosedCurlyBraces++;
} else {
throw "Unknown character found when curly brace expected.";
}
}
var possiblyCorrectlyFormattedJsonString = rawLogMessage.substring(locationOfFirstUnescapedOpeningCurly, locationOfCurrentCurly + 1);
jsonStrings.push(possiblyCorrectlyFormattedJsonString);
}
return jsonStrings;
}
//this will only find the next opening brace {
function GetLocationOfNextUnescapedOpeningCurlyBrace(rawLogMessage, startIndex) {
var regexNextUnescapedOpeningCurly = /(?<!\\)({)/i;
return RegexStringExtract(rawLogMessage, startIndex, regexNextUnescapedOpeningCurly)
}
//this will find the next opening OR closing brace { }
function GetLocationOfNextUnescapedCurlyBrace(rawLogMessage, startIndex) {
var regexNextUnescapedCurly = /(?<!\\)({|})/i;
return RegexStringExtract(rawLogMessage, startIndex, regexNextUnescapedCurly)
}
function RegexStringExtract(stringToSearch, startIndex, regex) {
var substring = stringToSearch.substring(startIndex);
var regexMatch = regex.exec(substring);
if (regexMatch) {
return startIndex + regexMatch.index;
}
else {
return -1;
}
}
str.substring(firstIndex,lastIndex+1)
即可满足大多数类似chatGPT这样的人工智能返回的消息。 - Ali Mert Çakarstr.substring(firstIndex,lastIndex+1)
即可满足像chatGPT这样的ai返回的大多数消息。 - Ali Mert Çakar