react实现点击获取json对象的jsonPath

  • Post author:
  • Post category:其他




准备

安装

react-json-view



npm install --save react-json-view

可参考的一些开源库:

react-json-path-picker



json-path-picker


线上工具:

jsonpath tool



JsonPath


JsonPath官方文档

用来解析多层嵌套的json数据。JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript, Python, PHP 和 Java。

本质: 通过一种语法规则

快速从 JSON 数据中提取数据

。类似于 正则表达式 通过一定规则从 text 文本内容提取数据。

语法规则:

在这里插入图片描述

参考文档:

JSON 数据提取



实现

import ReactJson from 'react-json-view';

interface Props {
  jsonValue: any;
  updateJsonPath: (value: string) => void;
}
export function JsonPathFilter(props: Props) {
  const { jsonValue, updateJsonPath } = props;

  const getValue = (select: any) => {
    const { name, namespace } = select;
    namespace.push(name);
    const reg = /^[0-9]*$/g;
    let path = '';
    namespace.forEach((s: string) => {
      if (reg.test(s)) {
        path = path?.substring(0, path.length - 1);
        path = `${path}[${s}].`;
      } else {
        path = `${path + s}.`;
      }
    });
    path = path?.substring(0, path.length - 1);
    return path;
  };

  return <ReactJson src={jsonValue} onSelect={(select) => updateJsonPath(getValue(select))} />;
}


select

数据类型:

在这里插入图片描述

效果图:

在这里插入图片描述



进一步完善

考虑到上述方案只能通过点击叶子结点的value来获取path,如果说我们点击

任意节点的key或者value都可以获取到path的话

,上述方案就不太可行,

react-json-view

开源库不提供对任意节点点击的监听事件。

调研发现,我们可以使用

jsoneditor

,注意官方给定的

onSelectionChang

方法,是针对选择多行(或者一行)时,起始节点数据,比如下图所示,选择的是一个区间。这种用法并不太符合我们的要求,我们希望的是对节点的点击事件进行监听。

在这里插入图片描述

在这里插入图片描述

查看文档,找到了

onEvent

方法,可以对节点的key和value进行事件监听,包括鼠标移入移除,点击,聚焦等事件。

在这里插入图片描述

这里,我们需要监听的是点击事件。

首先,我们先封装一下JsonEditor,代码如下,

JsonEditor/index.tsx:

import { useMemoizedFn } from 'ahooks';
import JSONEditor from 'jsoneditor';
import { useEffect, useState } from 'react';
import './index.less';

interface Props {
  jsonValue: any;
  otherOpts?: any;
  domId?: string;
  isExpandAll?: boolean;
  containerStyle?: any;
}

export default function JsonEditor(props: Props) {
  const { jsonValue, otherOpts = {}, domId = 'jsoneditor', isExpandAll, containerStyle } = props;
  const [jsonRef, setJsonRef] = useState<any>(null);
  let editor: any;

  const renderJsonEditor = useMemoizedFn(() => {
    const container = document.getElementById(domId);
    if (container) {
      container.innerHTML = ''; // 防止添加多个jsoneditor
      const options: any = {
        mode: 'view',
        modes: ['code', 'text', 'tree', 'view'],
        language: 'en',
        ...otherOpts,
      };
      editor = new JSONEditor(container, options);
      editor.set(jsonValue);
      if (isExpandAll) {
        editor.expandAll();
      }
    }
  });

  useEffect(() => {
    renderJsonEditor();
    return () => {
      editor?.destroy();
    };
  }, [jsonRef, renderJsonEditor, jsonValue, editor]);

  return <div style={containerStyle} ref={setJsonRef} id={domId} />;
}

JsonEditor/index.less:

div.jsoneditor-field,
div.jsoneditor-value {
  cursor: pointer;
}

调整后的JsonPathFilter代码如下,

JsonPathFilter/index.tsx:

import JsonEditor from '../JsonEditor';

interface Props {
  jsonValue: any;
  updateJsonPath: (value: string) => void;
  domId: string;
}
export function JsonPathFilter(props: Props) {
  const { jsonValue, updateJsonPath, domId } = props;

  const getValue = (namespace: any) => {
    let path = '';
    namespace?.forEach((s: string | number) => {
      if (typeof s === 'number') {
        path = path?.substring(0, path.length - 1);
        path = `${path}[${s}].`;
      } else {
        path = `${path + s}.`;
      }
    });
    path = path?.substring(0, path.length - 1);
    return path;
  };

  return (
    <JsonEditor
      jsonValue={jsonValue}
      domId={domId}
      otherOpts={{
        onEvent: (item: any, event: any) => {
          if (event.type === 'click') { // 判断事件类型
            // 监听点击 key 或者 value 的时候
            updateJsonPath(getValue(item.path));
          }
        },
      }}
    />
  );
}



版权声明:本文为weixin_43973415原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。