当前位置: 首页 > news >正文

2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类

1. 思路

  1. 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。
  2. 引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。

2. 工具类

pom.xml

<!-- commonmark 解析markdown -->
<dependency><groupId>org.commonmark</groupId><artifactId>commonmark</artifactId><version>0.21.0</version>
</dependency>
<!-- commonmark 解析markdown tables -->
<dependency><groupId>org.commonmark</groupId><artifactId>commonmark-ext-gfm-tables</artifactId><version>0.21.0</version>
</dependency>

MarkdownParseResult

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** Markdown解析结果* @Author: onecomer* @Date: 2021/1/26 16:00*/
@ApiModel(description = "Markdown解析结果")
@Data
public class MarkdownParseResult {@ApiModelProperty(value = "MarkdownHtml内容")private String htmlContent;@ApiModelProperty(value = "标题及内容集合",example = "{'标题1':'内容1','标题2':'内容2',...}")private JSONObject titles;@ApiModelProperty(value = "表格标题及内容集合",example = "{'表格标题':'{headers:['列1','列2'],rows:[{'值1','值2'},{'值1','值2'}]}",notes = "headers为表头,rows为行数据")private JSONObject tables;@ApiModelProperty(value = "无序列表集合",example = "{''无序列表标题:[{'无序列表内容1'},{'无序列表内容2'},...]}")private JSONObject unOrderedLists;@ApiModelProperty(value = "有序列表集合",example = "{''有序列表标题:[{'有序列表内容1'},{'有序列表内容2'},...]}")private JSONObject orderedLists;@ApiModelProperty(value = "代码块集合",example = "{'代码块标题1':{'codeBlockContent(固定值)':'代码块内容1','codeBlockType(固定值)':'代码块类型1'}}")private JSONObject codeBlocks;
}

MarkdownParserUtil

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TableBody;
import org.commonmark.ext.gfm.tables.TableCell;
import org.commonmark.ext.gfm.tables.TableHead;
import org.commonmark.ext.gfm.tables.TableRow;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.AbstractVisitor;
import org.commonmark.node.BulletList;
import org.commonmark.node.FencedCodeBlock;
import org.commonmark.node.Heading;
import org.commonmark.node.ListItem;
import org.commonmark.node.Node;
import org.commonmark.node.OrderedList;
import org.commonmark.node.Paragraph;
import org.commonmark.node.SoftLineBreak;
import org.commonmark.node.Text;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Markdown解析工具类* @Author: onecomer* @Date: 2021/1/26 16:00*/
public class MarkdownParserUtil {private static Parser parser;private static HtmlRenderer renderer;static {parser = Parser.builder().extensions(Arrays.asList(TablesExtension.create())).build();renderer = HtmlRenderer.builder().extensions(Arrays.asList(TablesExtension.create())).build();}/*** 读取并解析Markdown文件*/public static MarkdownParseResult parseMarkdownFile(String filePath) {String content = null;try {content = new String(Files.readAllBytes(Paths.get(filePath)));} catch (IOException e) {throw new RuntimeException(e);}MarkdownParseResult result = parseMarkdownFileContent(content);return result;}/*** 解析Markdown内容*/public static MarkdownParseResult parseMarkdownFileContent(String content) {Node document = parser.parse(content);MarkdownParseResult result = new MarkdownParseResult();
//        result.setHtmlContent(renderer.render(document));JSONObject titles = new JSONObject(true);JSONObject tables = new JSONObject(true);JSONObject unOrderedLists = new JSONObject(true);JSONObject orderedLists = new JSONObject(true);JSONObject codeBlocks = new JSONObject(true);String currentHeading = "";StringBuilder paragraphContent = new StringBuilder();boolean isDelReapeatTilte = true;Node node = document.getFirstChild();while (node != null) {if (node instanceof Heading) {// 标题String text = getText(node);currentHeading = text;// 只有标题的直接添加if (!((node.getNext()) instanceof Paragraph)) {titles.put(currentHeading, currentHeading);}} else if (node instanceof Paragraph) {String text = getText(node);// 普通文本paragraphContent.append(text).append("\n");// 结束添加paragraphContentif (!((node.getNext()) instanceof Paragraph)) {titles.put(currentHeading, paragraphContent.toString().trim());paragraphContent = new StringBuilder();}} else if (node instanceof BulletList) {// 无序列表JSONArray items = new JSONArray();Node listItem = node.getFirstChild();while (listItem != null) {if (listItem instanceof ListItem) {String text = getText(listItem);items.add(text);}listItem = listItem.getNext();}unOrderedLists.put(currentHeading, items);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof OrderedList) {// 有序列表JSONArray items = new JSONArray();Node listItem = node.getFirstChild();while (listItem != null) {if (listItem instanceof ListItem) {String text = getText(listItem);items.add(text);}listItem = listItem.getNext();}orderedLists.put(currentHeading, items);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof FencedCodeBlock) {// 代码块FencedCodeBlock codeBlock = (FencedCodeBlock) node;JSONObject codeBlockInfo = new JSONObject(true);String codeBlockContent = codeBlock.getLiteral();String codeBlockType = codeBlock.getInfo();codeBlockInfo.put("codeBlockContent", codeBlockContent);codeBlockInfo.put("codeBlockType", codeBlockType);codeBlocks.put(currentHeading, codeBlockInfo);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof TableBlock) {// 表格JSONObject tableInfo = new JSONObject(true);JSONArray headers = new JSONArray();JSONArray rows = new JSONArray();// TableHeadNode row = node.getFirstChild();if (row instanceof TableHead) {Node headerRow = row.getFirstChild();if (headerRow instanceof TableRow) {Node cell = headerRow.getFirstChild();while (cell != null) {if (cell instanceof TableCell) {String text = getText(cell);headers.add(text);}cell = cell.getNext();}}}// TableBodyNode tableBody = row.getNext();while (tableBody != null) {if (tableBody instanceof TableBody) {// TableRowNode tableRow = tableBody.getFirstChild();while (tableRow != null) {if (tableRow instanceof TableRow) {JSONArray rowData = new JSONArray();Node tableCell = tableRow.getFirstChild();while (tableCell != null) {if (tableCell instanceof TableCell) {String text = getText(tableCell);rowData.add(text);}tableCell = tableCell.getNext();}rows.add(rowData);}tableRow = tableRow.getNext();}}tableBody = tableBody.getNext();}tableInfo.put("headers", headers);tableInfo.put("rows", rows);tables.put(currentHeading, tableInfo);if (isDelReapeatTilte) {titles.remove(currentHeading);}}// 处理下一个节点node = node.getNext();}result.setTitles(titles);result.setTables(tables);result.setUnOrderedLists(unOrderedLists);result.setOrderedLists(orderedLists);result.setCodeBlocks(codeBlocks);return result;}/*** 获取节点的文本内容(包含格式)*/private static String getText(Node node) {StringBuilder sb = new StringBuilder();node.accept(new AbstractVisitor() {@Overridepublic void visit(Text text) {sb.append(text.getLiteral());}//            @Override
//            public void visit(Emphasis emphasis) {
//                sb.append("*").append(getText(emphasis)).append("*");
//            }
//
//            @Override
//            public void visit(StrongEmphasis strongEmphasis) {
//                sb.append("**").append(getText(strongEmphasis)).append("**");
//            }
//
//            @Override
//            public void visit(Code code) {
//                sb.append("`").append(code.getLiteral()).append("`");
//            }});return sb.toString().trim();}/*** 判断是否为表格节点*/@Deprecatedprivate static boolean isTable(Node node) {
//        String content = getTextContent(node);
//        return content.contains("|") && content.contains("\n") && content.contains("---");Node firstChild = node.getFirstChild();Node secondChild = firstChild != null ? firstChild.getNext() : null;if (secondChild instanceof SoftLineBreak) {return true;}return false;}/*** 解析表格内容*/@Deprecatedprivate static JSONObject parseTable(Node tableNode) {String[] lines = getText(tableNode).split("\n");boolean isHeader = true;List<String> headers = new ArrayList<>();for (String line : lines) {line = line.trim();if (line.isEmpty() || line.startsWith("|---")) {isHeader = false;continue;}String[] cells = line.split("\\|");List<String> cleanCells = new ArrayList<>();for (String cell : cells) {String cleaned = cell.trim();if (!cleaned.isEmpty()) {cleanCells.add(cleaned);}}if (isHeader) {headers.addAll(cleanCells);
//                tableInfo.setHeaders(headers);} else {Map<String, String> row = new HashMap<>();for (int i = 0; i < headers.size() && i < cleanCells.size(); i++) {row.put(headers.get(i), cleanCells.get(i));}
//                tableInfo.getRows().add(row);}}return null;}public static void main(String[] args) {String filePath = "D:\\tab\\1_ideaIC-2022.2.win\\2_WS\\1_SAAS_hgit_2\\2_assembler_all\\3_biz-project\\api-manage\\markdown\\新增实体数据能力.md";
//            filePath = "D:\\tab\\1_ideaIC-2022.2.win\\2_WS\\1_SAAS_hgit_2\\2_assembler_all\\3_biz-project\\api-manage\\markdown\\新增实体数据能力2.md";MarkdownParseResult result = parseMarkdownFile(filePath);//            System.out.println("HTML内容:");
//            System.out.println(result.getHtmlContent());System.out.println("\n标题及内容:");System.out.println(result.getTitles().toJSONString());System.out.println("\n表格内容:");System.out.println(result.getTables().toJSONString());System.out.println("\n无序列表:");System.out.println(result.getUnOrderedLists().toJSONString());System.out.println("\n有序列表:");System.out.println(result.getOrderedLists().toJSONString());System.out.println("\n代码块:");System.out.println(result.getCodeBlocks().toJSONString());}
} 

3. 测试

测试结果

image-20250126155507486

image-20250126155201114

image-20250126155245693

markdown文件

# 新增实体数据能力## 接口说明用来新增一条记录用来新增一条记录2用来新增一条记录3## 资产类型:API## 应用- 应用S码:Sxx## 标签- 新增实体数据能力
- xxx系统
- Sxx
- 新增记录 数据管理## 版本- v1.0.0## 接口地址```json
{"测试地址": "{baseUrl}/model/{dataSource}/{entityName}/add","生产地址": "{baseUrl}/model/{dataSource}/{entityName}/add"
}
```## 调用前提```json
需要先部署低代码引擎微服务,部署文档链接如下:
开发环境引擎部署:https://ihaier.feishu.cn/wiki/LyitwBYg4i8fRDkpPC0crxpMnlg
运行环境引擎部署:https://ihaier.feishu.cn/wiki/ZG16wdmOiib658k39X1cuzlKnSe
```## 请求方式POST## 请求头Header| 参数名       | 类型   | 是否必填 | 参数说明                      |
| :----------- | :----- | :------- | :---------------------------- |
| Access-Token | String | 是       | 统一登录token,从账号中心获取 |
| Access-Token2 | String | 是       | 统一登录token,从账号中心获取 |## 请求参数类型@RequestBody## 请求参数| 参数名     | 是否必填 | 类型         | 描述                    |
| :--------- | :------- | :----------- | :---------------------- |
| field1     | 否       | String       | 字段1                   |
| field2     | 否       | Integer      | 字段2                   |
| entityName | 否       | Object/Array | 关联实体(一对一/一对多) |### 请求参数示例```json
{"field1": "","field2": 19,"entityName": {"field1": "","field2": ""},"entityName": [{"field1": "","field2": ""}]
}
```## 返回参数类型@ResponseBody## 返回参数| 参数名  | 类型    | 说明                         |
| :------ | :------ | :--------------------------- |
| code    | Integer | 响应码,0表示成功,非0表示失败 |
| message | String  | 提示消息                     |
| data    | Object  | 返回数据                     |
| data.id | String  | 主键ID                       |### 返回参数示例#### 正确```json
{"code": 0,"message": "success", "data": {"id": "主键ID"} 
}
```#### 错误```json
{"code": 400,"message": "请求参数错误"
}
```### 错误码| errorCode | errorMessage |
| :-------- | :----------- |
| 400       | 请求参数错误 |## 调用示例```json
// 请求示例
POST /model/myDataSource/User/add
{"name": "张三","age": 25,"department": {"id": "dept001","name": "技术部"}
}// 返回结果示例
{"code": 0,"message": "success","data": {"id": "user001"}
}
```## 实现逻辑### 时序图```mermaid
sequenceDiagramparticipant Clientparticipant APIparticipant Serviceparticipant DatabaseClient->>API: POST /model/{ds}/{entity}/addAPI->>Service: addEntity(data)Service->>Service: validateData(data)Service->>Database: insert(data)Database-->>Service: Return idService-->>API: Return resultAPI-->>Client: Return response
```### 业务逻辑1. 校验请求参数的合法性
2. 根据实体定义验证字段
3. 生成主键ID
4. 保存实体数据
5. 返回新增记录的ID### 三方服务无 

相关文章:

2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容&#xff0c;根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...

动态规划DP 最长上升子序列模型 登山(题目分析+C++完整代码)

概览检索 动态规划DP 最长上升子序列模型 登山 原题链接 AcWing 1014. 登山 题目描述 五一到了&#xff0c;ACM队组织大家去登山观光&#xff0c;队员们发现山上一共有N个景点&#xff0c;并且决定按照顺序来浏览这些景点&#xff0c;即每次所浏览景点的编号都要大于前一个…...

css-设置元素的溢出行为为可见overflow: visible;

1.前言 overflow 属性用于设置当元素的内容溢出其框时如何处理。 2. overflow overflow 属性的一些常见值&#xff1a; 1 visible&#xff1a;默认值。内容不会被剪裁&#xff0c;会溢出元素的框。 2 hidden&#xff1a;内容会被剪裁&#xff0c;不会显示溢出的部分。 3 sc…...

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美国家具零售商&#xff0c;总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品&#xff0c;满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…...

1、开始简单使用rag

文章目录 前言数据存放申请api开始代码安装依赖从文件夹中读取文档文档切块将分割嵌入并存储在向量库中检索部分代码构造用户接口演示提示 整体代码 前言 本章只是简单使用rag的一个示例&#xff0c;为了引出以后的学习&#xff0c;将整个rag的流程串起来 数据存放 一个示例…...

Linux Samba 低版本漏洞(远程控制)复现与剖析

目录 前言 漏洞介绍 漏洞原理 产生条件 漏洞影响 防御措施 复现过程 结语 前言 在网络安全的复杂生态中&#xff0c;系统漏洞的探索与防范始终是保障数字世界安全稳定运行的关键所在。Linux Samba 作为一款在网络共享服务领域应用极为广泛的软件&#xff0c;其低版本中…...

安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的&#xff08;如果代码有错漏&#xff0c;可查看源码&#xff09; 1.掌握LinearLayout、RelativeLayout、FrameLayout等布局的综合使用。 2.掌握ImageView、TextView、EditText、CheckBox、Button、RadioGroup、RadioButton、ListView、RecyclerView等控件在项目中的…...

【 AI agents】letta:2024年代理堆栈演进(中英文翻译)

The AI agents stack AI 代理堆栈 November 14, 2024 11月 14, 2024原文: The AI agents stack官方教程教程学习笔记: 【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理Understanding the AI agents landscape 了解 AI 代理环境 Although we see a …...

Java中 instanceof 的用法(详解)

目录 引言 基本语法 基本作用 1. 检查对象是否是指定类的实例 2. 检查对象是否是子类的实例 3. 检查对象是否实现某个接口 4.null 处理 错误分析&#xff1a; 5.综合对比示例 最后总结 注意事项 引言 instanceof 概念在多态中引出&#xff0c;因为在多态发生时&…...

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸

晚上23点10分前下单&#xff0c;第二天上午显示屏送到&#xff0c;检查外包装没拆封过。这个屏幕左下方有几个按键&#xff0c;按一按就开屏幕、按一按就关闭屏幕&#xff0c;按一按方便节省时间&#xff0c;也支持阅读等模式。 显示屏是 &#xff1a;AOC 27英寸 2K高清 100Hz…...

【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础

文章目录 1. 前言 本文章基于 RocketMQ 4.9.3 1. 前言 RocketMQ 存储部分系列文章&#xff1a; 【RocketMQ 存储】- RocketMQ存储类 MappedFile 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础...

S4 HANA明确税金本币和外币之间转换汇率确定(OBC8)

本文主要介绍在S4 HANA OP中明确明确税金本币和外币之间转换汇率确定(OBC8)相关设置。具体请参照如下内容&#xff1a; 明确税金本币和外币之间转换汇率确定(OBC8) 以上配置&#xff0c;我们可以根据不同公司代码所配置的使用不同的汇率来对税金外币和本币之间进行换算。来针对…...

Cocos Creator 3.8 2D 游戏开发知识点整理

目录 Cocos Creator 3.8 2D 游戏开发知识点整理 1. Cocos Creator 3.8 概述 2. 2D 游戏核心组件 (1) 节点&#xff08;Node&#xff09;与组件&#xff08;Component&#xff09; (2) 渲染组件 (3) UI 组件 3. 动画系统 (1) 传统帧动画 (2) 动画编辑器 (3) Spine 和 …...

梯度提升用于高效的分类与回归

使用 决策树&#xff08;Decision Tree&#xff09; 实现 梯度提升&#xff08;Gradient Boosting&#xff09; 主要是模拟 GBDT&#xff08;Gradient Boosting Decision Trees&#xff09; 的原理&#xff0c;即&#xff1a; 第一棵树拟合原始数据计算残差&#xff08;负梯度…...

【单细胞第二节:单细胞示例数据分析-GSE218208】

GSE218208 1.创建Seurat对象 #untar(“GSE218208_RAW.tar”) rm(list ls()) a data.table::fread("GSM6736629_10x-PBMC-1_ds0.1974_CountMatrix.tsv.gz",data.table F) a[1:4,1:4] library(tidyverse) a$alias:gene str_split(a$alias:gene,":",si…...

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例&#xff1a;模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…...

新春登蛇山:告别岁月,启航未来

大年初一&#xff0c;晨曦透过薄雾&#xff0c;温柔地洒在武汉的大街小巷。2025 年的蛇年春节&#xff0c;带着新春的喜气与希望悄然而至。我站在蛇山脚下&#xff0c;心中涌动着复杂的情感&#xff0c;因为今天&#xff0c;我不仅将与家人一起登山揽胜&#xff0c;更将在这一天…...

hive:基本数据类型,关于表和列语法

基本数据类型 Hive 的数据类型分为基本数据类型和复杂数据类型 加粗的是常用数据类型 BOOLEAN出现ture和false外的其他值会变成NULL值 没有number,decimal类似number 如果输入的数据不符合数据类型, 映射时会变成NULL, 但是数据本身并没有被修改 创建表 创建表的本质其实就是在…...

安装最小化的CentOS7后,执行yum命令报错Could not resolve host mirrorlist.centos.org; 未知的错误

文章目录 安装最小化的CentOS7后&#xff0c;执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知的错误"错误解决方案&#xff1a; 安装最小化的CentOS7后&#xff0c;执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知…...

图论——spfa判负环

负环 图 G G G中存在一个回路&#xff0c;该回路边权之和为负数&#xff0c;称之为负环。 spfa求负环 方法1:统计每个点入队次数, 如果某个点入队n次, 说明存在负环。 证明&#xff1a;一个点入队n次&#xff0c;即被更新了n次。一个点每次被更新时所对应最短路的边数一定是…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...