#
vincentlu
2025-05-13 ebd2f4397a92c6a5096de1b86d59154363344720
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import React, { useState, useRef, useEffect } from 'react';
import { Box, Typography, Paper, useTheme } from '@mui/material';
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
import jsonLang from 'react-syntax-highlighter/dist/esm/languages/hljs/json';
import { xcode, atomOneDark, a11yLight } from 'react-syntax-highlighter/dist/esm/styles/hljs';
 
// https://react-syntax-highlighter.github.io/react-syntax-highlighter/demo/
 
const parseJson = (jsonStr) => {
    let json = '';
    try {
        const jsonObj = typeof jsonStr === 'string' ? JSON.parse(jsonStr) : jsonStr;
        json = JSON.stringify(jsonObj, null, 2);
    } catch (error) {
        json = 'Invalid JSON';
    }
    return json;
}
 
SyntaxHighlighter.registerLanguage('json', jsonLang);
 
const JsonShow = ({ data, height = 500 }) => {
    const theme = useTheme();
    const themeMode = theme.palette.mode;
 
    const [json, setJson] = useState(null);
 
    useEffect(() => {
        if (data) {
            setJson(parseJson(data));
        }
    }, [data]);
 
    return (
        <Paper
            elevation={3}
            sx={{
                padding: 2,
                maxHeight: height,
                overflow: 'auto',
                backgroundColor: theme.palette.background.paper,
                borderRadius: 2,
            }}
        >
            <pre style={{ margin: 0, fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
                {json === 'Invalid JSON' ? (
                    <Typography color="error">Invalid JSON</Typography>
                ) : (
 
                    <SyntaxHighlighter
                        language="json"
                        style={themeMode === 'dark' ? atomOneDark : xcode}
                        customStyle={{
                            backgroundColor: 'transparent',
                            padding: 0,
                            fontSize: '0.875rem', // 14px
                            fontFamily: 'monospace',
                            whiteSpace: 'pre-wrap',
                            wordBreak: 'break-word',
                            // fontWeight: 'bold',
                        }}
                        showLineNumbers
                    >
                        {json}
                    </SyntaxHighlighter>
                    // renderFormattedJson(json)
                )}
            </pre>
        </Paper>
    );
}
 
const renderFormattedJson = (json) => {
    const regex = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(\.\d*)?([eE][+\-]?\d+)?) /g;
    const parts = json.split(regex);
 
    return parts.map((part, index) => {
        if (!part) return null;
        let style = {};
 
        if (/^"/.test(part)) {
            if (/:$/.test(part)) {
                style = { color: '#b22222' }; // key
            } else {
                style = { color: '#1e90ff' }; // string
            }
        } else if (/true|false/.test(part)) {
            style = { color: '#228B22' }; // boolean
        } else if (/null/.test(part)) {
            style = { color: '#808080' }; // null
        } else if (/^-?\d+/.test(part)) {
            style = { color: '#FF8C00' }; // number
        }
 
        return (
            <span key={index} style={style}>
                {part}
            </span>
        );
    });
 
};
 
 
export default JsonShow;