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

准备

安装 react-json-viewnpm install --save react-json-view

可参考的一些开源库:react-json-path-pickerjson-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));
          }
        },
      }}
    />
  );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值