You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React+Material UI中解析API返回的复杂嵌套JSON并展示

解决方案

步骤1:解析嵌套JSON字符串

note.notes是JSON格式的字符串,需先用JSON.parse()解析为JavaScript对象,同时加入错误处理避免解析失败导致页面崩溃。

步骤2:提取并格式化文本内容

从解析后的对象中提取核心文本,处理换行符\n,并应用标记中的样式(文本颜色、背景色)。可编写辅助函数完成内容提取与样式映射。

步骤3:用Material UI组件渲染

使用Typography、Box等组件,结合提取的样式与文本内容,实现美观展示。


修改后的完整代码

import React, { useEffect, useState } from 'react';
import { Container, Typography, Card, CardContent, Grid, Box } from '@mui/material';
import axios from 'axios';

// 辅助函数:解析notes并提取带样式的内容
const parseNotesContent = (notesStr) => {
  try {
    const notesObj = JSON.parse(notesStr);
    // 遍历嵌套结构找到包含文本的节点
    const textNode = notesObj.content?.[0]?.content?.find(block => 
      block.content?.[0]?.content?.[0]?.type === 'text'
    )?.content?.[0]?.content?.[0];
    
    if (!textNode) return null;
    
    // 提取样式参数与文本内容
    const text = textNode.text;
    const marks = textNode.marks || [];
    const textColor = marks.find(m => m.type === 'textColor')?.attrs?.color || 'inherit';
    const bgColor = marks.find(m => m.type === 'backgroundColor')?.attrs?.color || 'transparent';
    
    // 拆分换行符为独立行
    const textLines = text.split('\n').filter(line => line.trim() !== '');
    
    return { textLines, textColor, bgColor };
  } catch (err) {
    console.error('解析notes失败:', err);
    return null;
  }
};

function App() {
  const [notes, setNotes] = useState([]);

  useEffect(() => {
    axios.get('https://api.gyanibooks.com/library/get_dummy_notes')
      .then((res) => {
        setNotes(res.data);
      })
      .catch(err => {
        console.error(err);
      });
  }, []);

  return (
    <Container>
      <Typography variant="h4" gutterBottom>
        Notes
      </Typography>
      <Grid container spacing={2}>
        {notes.map((note) => {
          const parsedContent = parseNotesContent(note.notes);
          return (
            <Grid item xs={12} key={note.id}>
              <Card>
                <CardContent>
                  <Typography variant="h6" gutterBottom>
                    {note.title}
                  </Typography>
                  <Typography variant="subtitle1" gutterBottom>
                    ID: {note.id}
                  </Typography>
                  <Typography variant="subtitle1" gutterBottom>
                    Category: {note.category}
                  </Typography>
                  <Typography variant="subtitle1" gutterBottom>
                    User: {note.user}
                  </Typography>
                  {parsedContent ? (
                    <Box 
                      sx={{ 
                        mt: 2,
                        color: parsedContent.textColor,
                        backgroundColor: parsedContent.bgColor,
                        p: 2,
                        borderRadius: 1
                      }}
                    >
                      {parsedContent.textLines.map((line, index) => (
                        <Typography 
                          key={index} 
                          variant="body1" 
                          gutterBottom
                          sx={{ whiteSpace: 'pre-line' }}
                        >
                          {line}
                        </Typography>
                      ))}
                    </Box>
                  ) : (
                    <Typography variant="body2" color="error" mt={2}>
                      内容解析失败
                    </Typography>
                  )}
                </CardContent>
              </Card>
            </Grid>
          );
        })}
      </Grid>
    </Container>
  );
}

export default App;

代码说明

  • 解析处理:parseNotesContent函数负责JSON字符串解析,捕获解析错误避免页面崩溃;同时遍历嵌套结构提取文本与样式属性。
  • 样式应用:通过Material UI的sx属性,将提取的文本颜色、背景色应用到容器,提升内容可读性。
  • 换行处理:使用whiteSpace: 'pre-line'让\n自动转换为换行,拆分文本为独立Typography组件优化列表展示。
  • 错误降级:解析失败时显示友好错误提示,保证页面可用性。

内容的提问来源于stack exchange,提问作者Aach_copro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:20:20