背景
由于历史原因,项目中 JSON 编辑器使用的是 react-json-editor-ajrm,近期遇到一个严重的展示错误,传入编辑器的数据与展示的不一致,这是产品和用户不可接受的。
工具介绍
react-json-editor-ajrm 可以用于查看、编辑和校验 JSON 对象。但这个项目已经不再积极维护,并计划在2023年6月15日废弃。
Warning: As you may already know, the react-json-editor-ajrm's orignal project is not actively maintained and that it will eventually be deprecated. So I've decided to set an official date for deprecation. The tentative date for this is June 15, 2023.
问题复现
使用官方示例
这里仅把测试数据换成能复现问题的数据(在解析嵌套带引号数据时会出问题)
js
复制代码
export const testData = {
"key1": "{"test":"{\"name\":\"editor\"}"}",
"key2": "{"name":"editor"}",
"key3": {
"name": "editor"
}
}
jsx
复制代码
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./index.css";
import JSONInput from "react-json-editor-ajrm/index";
import locale from "react-json-editor-ajrm/locale/en";
import { testData } from "./testData";
class App extends Component {
render() {
/**
* Rendering this JSONInput component with some properties
*/
return (
<div style={{ maxWidth: "1400px", maxHeight: "100%" }}>
<JSONInput
placeholder={testData} // data to display
theme="light_mitsuketa_tribute"
locale={locale}
colors={{
string: "#DAA520" // overrides theme colors with whatever color value you want
}}
height="550px"
onChange={(e) => {
console.log("jsoneditor-onchange-e", e);
}}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"));
渲染效果如图:
很明显能看出问题,key1、key2 的展示都跟原始数据不一致
探究原因
这是用一个常用的 JSON 格式化工具的展示效果。证明数据是没问题的,而是 react-json-editor-ajrm 内部处理逻辑导致的问题。
深入分析 react-json-editor-ajrm 源码,发现 this.tokenize 函数在处理传入数据时出现了问题。这导致了数据标记(tokens)的生成错误,进一步导致 markupText 的错误,最终影响了数据的展示。
分析链路
- render 函数中,dangerouslySetInnerHTML: this.createMarkup(markupText)
- showPlaceholder 函数中
jsx
复制代码
const data = this.tokenize(placeholder);
this.setState({
prevPlaceholder: placeholder,
plainText: data.indentation,
markupText: data.markup,
lines: data.lines,
error: data.error
});
- placeholder 是传入的数据
- markupText 取自 this.tokenize(placeholder),然后更新
- 关键在于 this.tokenize 对 placeholder 的处理,这里直接给出 this.tokenize 调用后的结果,感兴趣的可以查看源码
markup
jsx
复制代码
"<span type="symbol" value="{" depth="1" style="color:#D4D4D4">{</span><br> <span type="key" value="key1" depth="1" style="color:#59A5D8">key1</span><span type="symbol" value=":" depth="1" style="color:#49B8F7">:</span> <span type="string" value="'{'" depth="1" style="color:#DAA520">'{'</span><span type="" value="" depth="1" style="color:#D4D4D4"></span><span type="string" value="':'" depth="1" style="color:#DAA520">':'</span><span type="symbol" value="{" depth="2" style="color:#D4D4D4">{</span><br> <span type="key" value="'name\'" depth="2" style="color:#59A5D8">'name\'</span><span type="symbol" value=":" depth="2" style="color:#49B8F7">:</span> <span type="string" value="'editor\'" depth="2" style="color:#DAA520">'editor\'</span><br> <span type="symbol" value="}" depth="1" style="color:#D4D4D4">}</span><span type="key" value="'}'" depth="1" style="color:#59A5D8">'}'</span><span type="symbol" value="," depth="1" style="color:#D4D4D4">,</span><br> <span type="key" value="key2" depth="1" style="color:#59A5D8">key2</span><span type="symbol" value=":" depth="1" style="color:#49B8F7">:</span> <span type="string" value="'{'" depth="1" style="color:#DAA520">'{'</span><span type="" value="" depth="1" style="color:#D4D4D4"></span><span type="string" value="':'" depth="1" style="color:#DAA520">':'</span><span type="" value="" depth="1" style="color:#D4D4D4"></span><span type="string" value="'}'" depth="1" style="color:#DAA520">'}'</span><span type="symbol" value="," depth="1" style="color:#D4D4D4">,</span><br> <span type="key" value="key3" depth="1" style="color:#59A5D8">key3</span><span type="symbol" value=":" depth="1" style="color:#49B8F7">:</span> <span type="symbol" value="{" depth="2" style="color:#D4D4D4">{</span><br> <span type="key" value="name" depth="2" style="color:#59A5D8">name</span><span type="symbol" value=":" depth="2" style="color:#49B8F7">:</span> <span type="string" value="'editor'" depth="2" style="color:#DAA520">'editor'</span><br> <span type="symbol" value="}" depth="1" style="color:#D4D4D4">}</span><br><span type="symbol" value="}" depth="0" style="color:#D4D4D4">}</span>"
解决方案
由于这是 react-json-editor-ajrm 内部处理逻辑导致的,所以只能考虑更换依赖包。
调研发现可以使用 jsoneditor-react,这里给出简单的示例:
jsx
复制代码
import { JsonEditor as Editor } from 'jsoneditor-react';
import 'jsoneditor-react/es/editor.min.css';
import React from 'react'
import { testData } from './testData';
function App() {
return (
<Editor
value={testData}
onChange={(val) => {
console.log("jsoneditor-react-val", val);
}}
/>
)
}
export default App
项目启动后,发现展示是符合预期的,也没有别的问题,可以使用 jsoneditor-react 作为替换的三方包。
工具对比
react-json-editor-ajrm vs jsoneditor-react
在 npmtrends.com/ 中对两个工具的下载趋势进行了对比
pkg | 简介 | star | 地址 |
---|---|---|---|
react-json-editor-ajrm | A stylish, editor-like, modular, react component for viewing, editing, and debugging javascript object syntax! | 354 | github.com/AndrewRedic… |
jsoneditor-react | react wrapper implementation for jsoneditor | 262 | github.com/vankop/json… |
jsoneditor | - | 11.3k | github.com/josdejong/j… |
虽然从下载量以及 GitHub star 数量来看,jsoneditor-react 并不如 react-json-editor-ajrm,但 jsoneditor-react 是基于 jsoneditor 二次封装的,所以稳定性还是有一定的保障。
源文:react-json-editor-ajrm 解析错误与解决方案
如有侵权请联系站点删除!
Technical cooperation service hotline, welcome to inquire!