【写在前面】在实习中,遇到了如下需求:
待格式化数据大概长这样,里面存在Json乱码以及由$$包裹的公式
目标格式:
一、Json格式化
我们这里的任务主要分为两部分:
- 解析一个可能包含嵌套的 JSON 字符串
- 格式化 JSON 对象
因为我们不知道后端返回的数据嵌套了多少层,所以均采用递归的方式,具体代码如下:
1、解析一个可能包含嵌套的 JSON 字符串
parseAndFormatNestedJson(jsonString) {
const recursiveParse = jsonStr => {
try {
let parsedData = JSON.parse(jsonStr);
if (typeof parsedData === 'string') {
return recursiveParse(parsedData);
}
for (let key in parsedData) {
if (typeof parsedData[key] === 'string') {
try {
parsedData[key] = recursiveParse(parsedData[key]);
} catch (e) {
// 保留原始字符串
}
}
}
return parsedData;
} catch (e) {
return jsonStr;
}
};
const parsedResult = recursiveParse(jsonString);
return this.formatJson(parsedResult).replace(/\$\$/g, '$').replace(/\\\\/g, '\\');
},
这个函数的目的是解析一个可能包含嵌套的 JSON 字符串,并调用
formatJson
函数来格式化解析后的对象。处理过程如下:
-
递归解析 (
recursiveParse
): 这是一个内部函数,使用递归来处理嵌套的 JSON 字符串。- 使用
JSON.parse
尝试解析输入的字符串jsonStr
。 - 如果解析后的结果是字符串类型,表示可能是嵌套的 JSON 字符串,因此再次调用
recursiveParse
来解析这个字符串。 - 如果结果是一个对象,遍历该对象的每个属性。如果属性值是字符串类型,尝试对这个字符串进行递归解析。
- 如果在解析过程中遇到异常(比如非法的 JSON 格式),会捕获异常并返回原始字符串。
- 使用
-
格式化和替换: 解析完成后的 JSON 对象通过
formatJson
进行格式化。格式化完成后,使用字符串替换来处理特殊字符,如将$$
替换为$(方便展示)
,将\\\\
替换为\\(处理异常)
2、格式化 JSON 对象
formatJson(obj, level = 0) {
const spaces = ' '.repeat(level);
if (typeof obj !== 'object' || obj === null) {
return JSON.stringify(obj);
}
if (Array.isArray(obj)) {
const items = obj.map(item => `\n${spaces} ${this.formatJson(item, level + 1)}`);
return `[${items.join(', ')}\n${spaces}]`;
} else {
const entries = Object.entries(obj).map(([key, value]) =>
`\n${spaces} "${key}": ${this.formatJson(value, level + 1)}`
);
return `{${entries.join(', ')}\n${spaces}}`;
}
}
这个函数用于格式化 JSON 对象,使其更易于阅读。它支持递归格式化对象和数组。
- 基础情况: 如果输入不是对象(包括数组),或者为
null
,直接使用JSON.stringify
来转换为字符串。 - 数组处理: 如果是数组,对每个元素递归调用
formatJson
并增加缩进,然后将结果拼接成完整的数组格式。 - 对象处理: 如果是对象,对每个键值对递归调用
formatJson
并增加缩进,然后将结果拼接成完整的对象格式。
二、渲染latex公式
这里涉及到 第三方库 Mathjax 的使用,Mathjax具有强大的功能,配置好latex的规则后,可以自动识别 $$ / $ 包裹的公式,并将公式优雅的呈现在页面上。
1、引入并配置
我这里使用的 cdn 引入的方式,在vue项目的 index.html 中 <head> 下配置
<!-- 配置 MathJax -->
<script>
window.MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$'], ['\\[', '\\]']]
},
svg: {
fontCache: 'global'
}
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script>
2、组件中使用
<template>
<div>
<div id="json-container">{
{ formattedJson }}</div>
<!-- <div id="json-container">{
{ this.parseAndFormatNestedJson(this.jsonString) }}</div> -->
</div>
</template>
mounted() {
this.$nextTick(() => {
MathJax.typeset();
});
3、配置样式
配置到这里,你会发现页面上的公式正常渲染了,但是字符串的格式却乱了,所以需要加一些样式,代码如下: