前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >自己手撸一个 JSON 解析器

自己手撸一个 JSON 解析器

作者头像
好好学java
发布于 2019-10-22 06:32:38
发布于 2019-10-22 06:32:38
1K00
代码可运行
举报
运行总次数:0
代码可运行

作者:omgleoo

JSON

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。

JSON与JS的区别以及和XML的区别具体请参考百度百科:

https://baike.baidu.com/item/JSON/2462549?fr=aladdin

JSON有两种结构:

第一种:对象

“名称/值”对的集合不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。

对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{"姓名": "张三", "年龄": "18"}

第二种:数组

值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。

值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
    { 
    "姓名": "张三",          
    "年龄":"18"    
    },

    {        
    "姓名": "里斯",          
    "年龄":"19"   

    }
]

通过上面的了解可以看出,JSON存在以下几种数据类型(以Java做类比):

json

java

string

Java中的String

number

Java中的Long或Double

true/false

Java中的Boolean

null

Java中的null

[array]

Java中的List或Object[]

{“key”:”value”}

Java中的Map<String, Object>

解析JSON

JSON解析器的基本原理

输入一串JSON字符串,输出一个JSON对象。

步骤

JSON解析的过程主要分以下两步:

第一步:对于输入的一串JSON字符串我们需要将其解析成一组token流。

例如 JSON字符串{“姓名”: “张三”, “年龄”: “18”} 我们需要将它解析成

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{、 姓名、 :、 张三、 ,、 年龄、 :18}

这样一组token流

第二步:根据得到的token流将其解析成对应的JSON对象(JSONObject)或者JSON数组(JSONArray)

下面我们来详细分析下这两个步骤:

获取token流

根据JSON格式的定义,token可以分为以下几种类型

token

含义

NULL

null

NUMBER

数字

STRING

字符串

BOOLEAN

true/false

SEP_COLON

:

SEP_COMMA

,

BEGIN_OBJECT

{

END_OBJECT

}

BEGIN_ARRAY

[

END_ARRAY

]

END_DOCUMENT

表示JSON数据结束

根据以上的JSON类型,我们可以将其封装成enum类型的TokenType

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.json.demo.tokenizer;
/**
 BEGIN_OBJECT({)
 END_OBJECT(})
 BEGIN_ARRAY([)
 END_ARRAY(])
 NULL(null)
 NUMBER(数字)
 STRING(字符串)
 BOOLEAN(true/false)
 SEP_COLON(:)
 SEP_COMMA(,)
 END_DOCUMENT(表示JSON文档结束)
 */

public enum TokenType {
    BEGIN_OBJECT(1),
    END_OBJECT(2),
    BEGIN_ARRAY(4),
    END_ARRAY(8),
    NULL(16),
    NUMBER(32),
    STRING(64),
    BOOLEAN(128),
    SEP_COLON(256),
    SEP_COMMA(512),
    END_DOCUMENT(1024);

    private int code;    // 每个类型的编号

    TokenType(int code) {
        this.code = code;
    }

    public int getTokenCode() {
        return code;
    }
}

在TokenType中我们为每一种类型都赋一个数字,目的是在Parser做一些优化操作(通过位运算来判断是否是期望出现的类型)

在进行第一步之前JSON串对计算机来说只是一串没有意义的字符而已。第一步的作用就是把这些无意义的字符串变成一个一个的token,上面我们已经为每一种token定义了相应的类型和值。所以计算机能够区分不同的token,并能以token为单位解读JSON数据。

下面我们封装一个token类来存储每一个token对应的值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.json.demo.tokenizer;

/**
 * 存储对应类型的字面量
 */

public class Token {
    private TokenType tokenType;
    private String value;

    public Token(TokenType tokenType, String value) {
        this.tokenType = tokenType;
        this.value = value;
    }

    public TokenType getTokenType() {
        return tokenType;
    }

    public void setTokenType(TokenType tokenType) {
        this.tokenType = tokenType;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Token{" +
                "tokenType=" + tokenType +
                ", value='" + value + '\'' +
                '}';
    }
}

在解析的过程中我们通过字符流来不断的读取字符,并且需要经常根据相应的字符来判断状态的跳转。所以我们需要自己封装一个ReaderChar类,以便我们更好的操作字符流。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.json.demo.tokenizer;

import java.io.IOException;
import java.io.Reader;

public class ReaderChar {
    private static final int BUFFER_SIZE = 1024;
    private Reader reader;
    private char[] buffer;
    private int index;      // 下标
    private int size;

    public ReaderChar(Reader reader) {
        this.reader = reader;
        buffer = new char[BUFFER_SIZE];
    }

    /**
     * 返回 pos 下标处的字符,并返回
     * @return
     */
    public char peek() {
        if (index - 1 >= size) {
            return (char) -1;
        }

        return buffer[Math.max(0, index - 1)];
    }

    /**
     * 返回 pos 下标处的字符,并将 pos + 1,最后返回字符
     * @return
     * @throws IOException
     */
    public char next() throws IOException {
        if (!hasMore()) {
            return (char) -1;
        }

        return buffer[index++];
    }

    /**
     * 下标回退
     */
    public void back() {
        index = Math.max(0, --index);
    }

    /**
     * 判断流是否结束
     */
    public boolean hasMore() throws IOException {
        if (index < size) {
            return true;
        }

        fillBuffer();
        return index < size;
    }

    /**
     * 填充buffer数组
     * @throws IOException
     */
    void fillBuffer() throws IOException {
        int n = reader.read(buffer);
        if (n == -1) {
            return;
        }

        index = 0;
        size = n;
    }
}

另外我们还需要一个TokenList来存储解析出来的token流

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.json.demo.tokenizer;

import java.util.ArrayList;
import java.util.List;

/**
 * 存储词法解析所得的token流
 */
public class TokenList {
    private List<Token> tokens = new ArrayList<Token>();
    private int index = 0;

    public void add(Token token) {
        tokens.add(token);
    }

    public Token peek() {
        return index < tokens.size() ? tokens.get(index) : null;
    }

    public Token peekPrevious() {
        return index - 1 < 0 ? null : tokens.get(index - 2);
    }

    public Token next() {
        return tokens.get(index++);
    }

    public boolean hasMore() {
        return index < tokens.size();
    }

    @Override
    public String toString() {
        return "TokenList{" +
                "tokens=" + tokens +
                '}';
    }
}

JSON解析比其他文本解析要简单的地方在于,我们只需要根据下一个字符就可知道接下来它所期望读取的到的内容是什么样的。如果满足期望了,则返回 Token,否则返回错误。

为了方便程序出错时更好的debug,程序中自定义了两个exception类来处理错误信息。(具体实现参考exception包)

下面就是第一步中的重头戏(核心代码):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public TokenList getTokenStream(ReaderChar readerChar) throws IOException {
        this.readerChar = readerChar;
        tokenList = new TokenList();

        // 词法解析,获取token流
        tokenizer();

        return tokenList;
    }

    /**
     * 将JSON文件解析成token流
     * @throws IOException
     */
    private void tokenizer() throws IOException {
        Token token;
        do {
            token = start();
            tokenList.add(token);
        } while (token.getTokenType() != TokenType.END_DOCUMENT);
    }

    /**
     * 解析过程的具体实现方法
     * @return
     * @throws IOException
     * @throws JsonParseException
     */
    private Token start() throws IOException, JsonParseException {
        char ch;
        while (true){   //先读一个字符,若为空白符(ASCII码在[0, 20H]上)则接着读,直到刚读的字符非空白符
            if (!readerChar.hasMore()) {
                return new Token(TokenType.END_DOCUMENT, null);
            }

            ch = readerChar.next();
            if (!isWhiteSpace(ch)) {
                break;
            }
        }

        switch (ch) {
            case '{':
                return new Token(TokenType.BEGIN_OBJECT, String.valueOf(ch));
            case '}':
                return new Token(TokenType.END_OBJECT, String.valueOf(ch));
            case '[':
                return new Token(TokenType.BEGIN_ARRAY, String.valueOf(ch));
            case ']':
                return new Token(TokenType.END_ARRAY, String.valueOf(ch));
            case ',':
                return new Token(TokenType.SEP_COMMA, String.valueOf(ch));
            case ':':
                return new Token(TokenType.SEP_COLON, String.valueOf(ch));
            case 'n':
                return readNull();
            case 't':
            case 'f':
                return readBoolean();
            case '"':
                return readString();
            case '-':
                return readNumber();
        }

        if (isDigit(ch)) {
            return readNumber();
        }

        throw new JsonParseException("Illegal character");
    }

在start方法中,我们将每个处理方法都封装成了单独的函数。主要思想就是通过一个死循环不停的读取字符,然后再根据字符的期待值,执行不同的处理函数。

下面我们详解分析几个处理函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private Token readString() throws IOException {
        StringBuilder sb = new StringBuilder();
        while(true) {
            char ch = readerChar.next();
            if (ch == '\\') {   // 处理转义字符
                if (!isEscape()) {
                    throw new JsonParseException("Invalid escape character");
                }
                sb.append('\\');
                ch = readerChar.peek();
                sb.append(ch);
                if (ch == 'u') {   // 处理 Unicode 编码,形如 \u4e2d。且只支持 \u0000 ~ \uFFFF 范围内的编码
                    for (int i = 0; i < 4; i++) {
                        ch = readerChar.next();
                        if (isHex(ch)) {
                            sb.append(ch);
                        } else {
                            throw new JsonParseException("Invalid character");
                        }
                    }
                }
            } else if (ch == '"') {     // 碰到另一个双引号,则认为字符串解析结束,返回 Token
                return new Token(TokenType.STRING, sb.toString());
            } else if (ch == '\r' || ch == '\n') {     // 传入的 JSON 字符串不允许换行
                throw new JsonParseException("Invalid character");
            } else {
                sb.append(ch);
            }
        }
    }

该方法也是通过一个死循环来读取字符,首先判断的是JSON中的转义字符。

JSON中允许出现的有以下几种

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
\"
\\
\b
\f
\n
\r
\t
\u four-hex-digits
\/

具体的处理方法封装在了isEscape()方法中,处理Unicode 编码时要特别注意一下u的后面会出现四位十六进制数。当读取到一个双引号或者读取到了非法字符(’\r’或’、’\n’)循环退出。

判断数字的时候也要特别小心,注意负数,frac,exp等等情况。

通过上面的解析,我们可以得到一组token,接下来我们需要以这组token作为输入,解析出相应的JSON对象

解析出JSON对象

解析之前我们需要定义出JSON对象(JSONObject)和JSON数组(JSONArray)的实体类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.json.demo.jsonstyle;

import com.json.demo.exception.JsonTypeException;
import com.json.demo.util.FormatUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JSON的对象形式
 * 对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
 */
public class JsonObject {
    private Map<String, Object> map = new HashMap<String, Object>();

    public void put(String key, Object value) {
        map.put(key, value);
    }

    public Object get(String key) {
        return map.get(key);
    }
    ...

}

package com.json.demo.jsonstyle;

import com.json.demo.exception.JsonTypeException;
import com.json.demo.util.FormatUtil;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * JSON的数组形式
 * 数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
 */
public class JsonArray {
    private List list = new ArrayList();

    public void add(Object obj) {
        list.add(obj);
    }

    public Object get(int index) {
        return list.get(index);
    }

    public int size() {
        return list.size();
    }
    ...
}

之后我们就可以写解析类了,由于代码较长,这里就不展示了。有兴趣的可以去GitHub上下载。实现逻辑比较简单,也易于理解。

解析类中的parse方法首先根据第一个token的类型选择调用parseJsonObject()或者parseJsonArray(),进而返回JSON对象或者JSON数组。上面的解析方法中利用位运算来判断字符的期待值既提高了程序的执行效率也有助于提高代码的ke’du’xi

完成之后我们可以写一个测试类来验证下我们的解析器的运行情况。我们可以自己定义一组JSON串也可以通过HttpUtil工具类从网上获取。最后通过FormatUtil类来规范我们输出。

具体效果如下图所示:

参考文章

http://www.cnblogs.com/absfree/p/5502705.html https://www.liaoxuefeng.com/article/0014211269349633dda29ee3f29413c91fa65c372585f23000?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io https://segmentfault.com/a/1190000010998941#articleHeader6 http://json.org/json-zh.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 好好学java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
撸一个 JSON 解析器
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
芋道源码
2019/05/13
1K0
自己动手实现一个简单的JSON解析器
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。相对于另一种数据交换格式 XML,JSON 有着诸多优点。比如易读性更好,占用空间更少等。在 web 应用开发领域内,得益于 JavaScript 对 JSON 提供的良好支持,JSON 要比 XML 更受开发人员青睐。所以作为开发人员,如果有兴趣的话,还是应该深入了解一下 JSON 相关的知识。本着探究 JSON 原理的目的,我将会在这篇文章中详细向大家介绍一个简单的JSON解析器的解析流程和实现细节。由于 JSON 本身比较简单,解析起来也并不复杂。所以如果大家感兴趣的话,在看完本文后,不妨自己动手实现一个 JSON 解析器。好了,其他的话就不多说了,接下来让我们移步到重点章节吧。
田小波
2018/04/29
4.1K15
自己动手实现一个简单的JSON解析器
高效JSON解析方案
JSON是常用的数据编码格式,在从海量JSON格式字符串数据中解析出所需值常常是计算的性能瓶颈,在大数据实时离线场景尤为常见。本文阐述一种高效解析JSON的方案和实现,相比较于jackson,在公司场景应用中,性能平均提升50%+。
一叶落知秋
2023/01/14
9680
高效JSON解析方案
android之JSON 进行网络数据交换「建议收藏」
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同一时候也易于机器解析和生成,很适合于server与client的交互。
全栈程序员站长
2022/07/07
4310
android之JSON 进行网络数据交换「建议收藏」
徒手撸一个JSON解析器
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。相对于另一种数据交换格式 XML,JSON 有着诸多优点。比如易读性更好,占用空间更少等。在 web 应用开发领域内,得益于 JavaScript 对 JSON 提供的良好支持,JSON 要比 XML 更受开发人员青睐。所以作为开发人员,如果有兴趣的话,还是应该深入了解一下 JSON 相关的知识。
南风
2019/12/18
8020
如何编写一个JSON解析器
编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构。
bear_fish
2018/09/20
9250
如何编写一个JSON解析器
Java高性能解析器实现思路及方法学习--Java编程
在某些情况下,你可能需要在Java中实现你自己的数据或语言解析器,也许是这种数据格式或语言缺乏标准的Java或开源解析器可以使用。或者虽然有现成的解析器实现,但它们要么太慢,要么太占内存,要么就是没有符合你所需要的特性。又或者是某个开源的解析器存在缺陷,要么是某个开源解析器的项目中止了,原因不一而足。不过无论原因是什么,总之事实就是你必须要自己去实现这个解析器。
用户1289394
2021/01/20
8720
Java高性能解析器实现思路及方法学习--Java编程
高性能Java解析器实现过程详解
高性能Java解析器实现过程详解 如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器。或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能。或者开源解析器存在缺陷,或者开源解析器项目被取消诸如此类原因。上述原因都没有你将需要实现你自己的解析器的事实重要。 当你必需实现自己的解析器时,你会希望它有良好表现,灵活,功能丰富,易于使用,最后但更重要是易于实现,毕竟你的名字会出现在代码中。本文中,我将介绍一种用Java实现高性能解析器
用户1289394
2018/02/27
2.3K0
高性能Java解析器实现过程详解
自己写的一个 json parser
之前看到知乎上有人问,会写Parser, Tokenizer是什么水平,绝大情况下,屁用没有。小部分情况,就看你运气了。因为这东西,面试又不会加分,而且,如果你面试的小公司,可能面试官甚至都不懂你在说啥。
MikeLoveRust
2020/05/26
1.4K0
json字符串与Object、List、Map的互转工具类
package com.cq2022.zago.base.util; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonFactory; import org.codehaus.ja
执笔记忆的空白
2020/12/25
1.7K0
语法解析器续:case..when表达式计算
之前写过一篇博客,是关于如何解析类似sql之类的解析器实现参考:https://www.cnblogs.com/yougewe/p/13774289.html
烂猪皮
2021/04/02
9210
lucene定义自己的分词器将其分成单个字符
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/115942.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/08
2480
数据库中间件 Sharding-JDBC 源码分析 —— SQL 解析(一)之语法解析
1. 概述 2. Lexer 词法解析器 3. Token 词法标记 3.2.1 Literals.IDENTIFIER 词法关键词 3.2.2 Literals.VARIABLE 变量 3.2.3 Literals.CHARS 字符串 3.2.4 Literals.HEX 十六进制 3.2.5 Literals.INT 整数 3.2.6 Literals.FLOAT 浮点数 3.1 DefaultKeyword 词法关键词 3.2 Literals 词法字面量标记 3.3 Symbol 词法符号标记 3
芋道源码
2018/03/02
9870
数据库中间件 Sharding-JDBC 源码分析 —— SQL 解析(一)之语法解析
Java中如何判断一个字符串是Java代码还是英文呢?
先给出以下两个字符串: 1、for (int i = 0; i< b.size(); i++) { 2、do something in English 从人工角度看,很显然第一个是Java代码,第二个是英语;那么在Java中如何通过代码检测第一个是Java代码,第二是英语呢? 第一个Java代码可能无法解析的,因为它并不是一个完整的方法或声明的表达式;下面为这一问题提供了解决方案。 解决的基本思路是将字符串转换为一组的令牌,例如,上面的代码行可能会成为“Java关键字、分隔符、运营商、标识符,……”;然后我
用户1289394
2018/02/27
1.3K0
IM通讯协议专题学习(五):Protobuf到底比JSON快几倍?全方位实测!
本系列的前几篇主要是从各个角度讲解Protobuf的基本概念、技术原理这些内容,但回过头来看,对比JSON这种事实上的数据协议工业标准,Protobuf到底性能到底高多少?
JackJiang
2022/12/16
6850
IM通讯协议专题学习(五):Protobuf到底比JSON快几倍?全方位实测!
从Gson 的一个著名Bug说起
Gson是一个源自谷歌的JSON序列化/反序列化框架,出身名门,社区活跃,因此被广泛应用。
Antony
2021/07/14
2K0
从Gson 的一个著名Bug说起
【安全研究】Jackson 学习笔记
Jackson框架是基于Java平台的一套数据处理工具,被称为"最好的Java Json解析器",目前Jackson主要有1.x和2.x两个分支版本,其中1.x的类库中包命名以org.codehaus.jackson.xxx开头,2.x类库中包命令com.fastxml.jackson.xxx开头,Jackson框架包含以下3个核心库:
Al1ex
2023/03/29
1.9K0
【安全研究】Jackson 学习笔记
实现JavaScript语言解释器(一)
对于大多数前端开发者来说JavaScript可谓是我们最熟悉的编程语言了,它十分强大可是有些语言特性却十分难以理解,例如闭包和this绑定等概念往往会让初学者摸不着头脑。网上有很多诸如《你看完这篇还不懂this绑定就来砍我》之类的文章来为大家传道解惑。可是在我看来这些文章大多流于表面,你读了很多可能还是会被面试官问倒。那么如何才能彻彻底底理解这些语言特性,从而在面试的时候立于不败之地呢?在我看来要想真的理解一样东西,最好的途径就是实现这样东西,这也是西方程序员非常喜欢说的learning by implementing。例如,你想更好地理解React,那么最好的办法就是你自己动手实现一个React。因此为了更好地理解JavaScript的语言特性,我就自己动手实现了一个叫做Simple的JavaScript语言解释器,这个解释器十分简单,它基于TypeScript实现了JavaScript语法的子集,主要包括下面这些功能:
进击的大葱
2022/08/22
1.3K0
实现JavaScript语言解释器(一)
4. JSON字符串是如何被解析的?JsonParser了解一下
各位好,我是A哥(YourBatman)。上篇文章:3. 懂了这些,方敢在简历上说会用Jackson写JSON 聊完,流式API的写部分可以认为你已完全掌握了,本文了解它读的部分。
YourBatman
2020/07/28
1.9K0
4. JSON字符串是如何被解析的?JsonParser了解一下
第8期 | jsmn,一个资源占用极少的json解析器
本专栏由Mculover666创建,主要内容为寻找嵌入式领域内的优质开源项目,一是帮助开发者使用开源项目实现更多的功能,二是通过这些开源项目,学习大佬的代码及背后的实现思想,提升自己的代码水平,和其它专栏相比,本专栏的优势在于:
Mculover666
2020/07/16
2K0
第8期 | jsmn,一个资源占用极少的json解析器
推荐阅读
相关推荐
撸一个 JSON 解析器
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文