1. 程式人生 > >開源Json解析器的淺述

開源Json解析器的淺述

之前在做專案中,Json 這種資料轉換格式經常用,為什麼呢?我認為是
1、它的易用性,跨平臺性,它是JS(JavaScript)的子集,是一種物件字面量。
2、它與XML都是樹結構的語法樹;
同樣的XML,JSON表示,Json則相對簡潔,XML相對冗餘,當然也是互相不可替代的,根據具體需求選擇合適才是完美的。

做個原生的Json解析器是掌閱科技的大佬提出的一個問題,在之前沒有相對的深入瞭解這個Json解析器,專案裡用到的都是org.Json開源包\Gson包。這周就主要對Json解析器包括與塌相關的知識做個梳理,形成網路結構。想做Json解析器,必須對Json本身有了解,在這裡主要點出幾個下面需要用的點:
JSON結構:

"string":Java的String;
number:Java的Long或Double;
true/false:Java的Booleannull:Java的null;
[array]:Java的List<Object>或Object[];
{"key":"value"}:Java的Map<String, Object>。

JSON文法:

Jsonobject = {} | { members }
members = pair | pair , members
pair = string : value
array = [] | [ elements ]
elements = value | value , elements
value = string | number | object | array | true | false | null
string = “” | ” chars ”
chars = char | char chars
char = any-Unicode-character-except-“-or–or- control-character | \” | \ | \/ | \b | \f | \n | \r | \t | \u four-hex-digits
number = int | int frac | int exp | int frac exp
int = digit | digit1-9 digits | - digit | - digit1-9 digits
frac = . digits
exp = e digits
digits = digit | digit digits
e = e | e+ | e- | E | E+ | E-
細節可以參看《Json必知必會》

http://download.csdn.net/download/qq_34417408/10122524

同時也要了解編譯原理的一些知識:
編譯過程:詞法分析,語法分析,語義分析,當然其中還有程式碼優化,目的碼;
其中,
詞法分析作用:找出單詞 。如int a=b+c; 結果為: int,a,=,b,+,c和;
語法分析作用:找出表示式,程式段,語句等。如int a=b=c;的語法分析結果為int a=b+c這條語句。
語義分析作用:檢視型別是否匹配等。

同時要了解解析器的功能,原理;
Json解析器是把輸入字串重新變成熟悉型別的物件,像一個函式,它的輸入是一個表示JSON的字串,輸出是結構化的對應到語言本身的資料結構。

在解析過程中,主要有兩部分一個是,詞法分析,將原始碼解析為詞法單元token;另一個是語法分析,構造語法樹parser;當然都是基於Json 詞法和文法。

在第一部分,形成詞法分析時,即是構造自動機(DFA);在寫Json之前,我先手寫了幾個簡單的自動機,很久沒寫過,熱了下身,其實只要邏輯分析沒問題,是很簡單的,就是程式碼實現。
(a|bb)一個可以有’a’和’b’的字串,’b’出現時必為偶數個;

public class ABB {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        // TODO code application logic here
        Scanner in =new Scanner(System.in);
        String string=in.nextLine();
        char[] ch=string.toCharArray();
        if(ch.length==0){
            throw new Exception("不合法字元!");
        }
        int i=0;
        while(i<ch.length){
            if(ch[i]=='a'){
                ++i;
            }else if(i<ch.length-1&&ch[i]=='b'){
                ++i;
                if(i<ch.length&&ch[i]=='b'){
                   ++i;
                }else{
                    throw new Exception("不合法字元!");
                }
            }else{
                throw new Exception("不合法字元!");
            }
        }
        System.out.println("合法字元!");
    }
}

由於Json 的結構特殊,在輸入第一字元的時候就可以判斷是哪個物件,{}/[]/string/true/false/number/null;我們可以加工構造並對應列舉型別即token流,進行詞法分析:

STRING(字串字面量)
NUMBER(數字字面量)
NULLnull)
START_ARRAY([)
END_ARRAY(])
START_OBJ({)
END_OBJ(})
COMMA(,)
COLON(:)
BOOLEAN(true或者false)
END_DOC(表示JSON資料的結束)

列舉型別:

public enum TokenType {
    START_OBJ, END_OBJ, START_ARRAY, END_ARRAY, NULL, NUMBER, STRING, BOOLEAN, COLON, COMMA, END_DOC
}

同時構造token類:

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

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

    public TokenType getType() {
        return type;
    }

    public void setType(TokenType type) {
        this.type = type;
    }

    public String getValue() {
        return value;
    }

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

    public String toString() {
        return getValue();
    }
}

在進行Json解析的詞法分析時,首先需要將字串轉為字元陣列,我們可以用BufferReader(new StringReader(String str));
關於BufferReader()可以見:https://www.cnblogs.com/meilidelaohuhua/p/6638545.html ;
轉化之後進行字元逐一分析,此時用到的是Json的結構的自動機,將其轉化為token流。此時第一部分詞法分析完成。
在第二部分語法樹parser構造中,主要分兩部分;
一塊是物件Object文法,一塊是陣列Array文法,其他文法是基本型別;
其中物件可以用Map實現(Key:Value),陣列用List集合

public class JObject implements Json {
    private Map<String, Value> map = new HashMap<>();
    public JObject(Map<String, Value> map) {
        this.map = map;
    }

    public int getInt(String key) {
        return Integer.parseInt((String) map.get(key).value());
    }

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

    public boolean getBoolean(String key) {
        return Boolean.parseBoolean((String) map.get(key).value());
    }

    public JArray getJArray(String key) {
        return (JArray) map.get(key).value();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{ ");
        int size = map.size();
        for (String key : map.keySet()) {
            sb.append(key + " : " + map.get(key));
            if (--size != 0) {
                sb.append(", ");
            }
        }
        sb.append(" }");
        return sb.toString();
    }
}
public class JArray implements  Json, Value {
    private List<Json> list = new ArrayList<>();

    public JArray(List<Json> list) {
        this.list = list;
    }

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

    public void add(Json element) {
        list.add(element);
    }

    public Json get(int i) {
        return list.get(i);
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[ ");
        for (int i =0; i < list.size(); i++) {
            sb.append(list.get(i).toString());
            if (i != list.size() - 1) {
                sb.append(", ");
            }
        }
        sb.append(" ]");
        return sb.toString();
    }

    @Override
    public Object value() {
        return this;
    }
}

其中重要的是Json,和Value抽象類的建立得以使JObject和JArray相互轉化,動態的完成物件和陣列相互巢狀的轉化。
另外,在構造token 類的時候把列舉型別和Value為屬性,在後面新增list的時候,省了許多麻煩。
原始碼:https://github.com/weiyanyanyan/Json

相關推薦

開源Json解析

之前在做專案中,Json 這種資料轉換格式經常用,為什麼呢?我認為是 1、它的易用性,跨平臺性,它是JS(JavaScript)的子集,是一種物件字面量。 2、它與XML都是樹結構的語法樹; 同樣的XML,JSON表示,Json則相對簡潔,XML相對冗餘,

一個簡單的json解析

har continue != objects token spa 根據 blog nbsp 實現一個簡單地json解析器。 兩部分組成,詞法分析、語法分析 詞法分析 package com.mahuan.json; import java.util.LinkedLis

自己動手實現一個簡單的JSON解析

pair bool 優點 輕量 結束 pan isdigit 復雜 false 1. 背景 JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。相對於另一種數據交換格式 XML,JSON 有著諸多優點。比如易讀性更好,占用空間更少等

一道面試題之關於自定義Json解析

最近在群裡裡面有哥們說在面試的時候,要求上機寫一個簡單的Json解析器,看到這個題目的時候,心裡慌得一比,因為感覺有些力不從心,不知道從哪裡下手,所以趕緊查了一下Gson原始碼,看看有什麼啟示沒有。當然,這篇扯淡並不是介紹Gson原始碼,而是想自定義一個簡單的Json解析器,來熟悉一下J

開源HTTP解析---http-parser和fast-http

轉載地址:https://www.cnblogs.com/arnoldlu/p/6497837.html 由於專案中遇到需要傳送http請求,然後再解析接收到的響應。大概在網上搜索了一下,有兩個比較不錯,分別是http-parser和fast-http。 http-parser是由C編寫的工

web專案---fastjson更加強大的json解析

首先,在之前的部落格我們談到了google開發的GSON,用來做java Bean物件與JSON之間的轉換,來完成前後端資料互動的統一,然後在之後又瞭解到有一個國產的比GSON效率更高的阿里巴巴開發的fastjson,具體效能對比可參考該作者寫的三種技術對比的部落格: Gson、FastJson

enumerator迭代和Iterator迭代

怎麼突然想起這個主題了呢?是在瀏覽關於HashMap和HashTable的相關效能的時候,瞭解到他們的迭代機制不同,就深入探討一下。HashMap和HashTable 主要區別是:執行緒安全、速度、迭代器;前兩個區別之前的部落格描述過,這裡只討論迭代器: 上原始碼: Enumer

Spring-Boot(一):使用自定義json解析

Spring-Boot是基於Spring框架的,它並不是對Spring框架的功能增強,而是對Spring的一種快速構建的方式。Spring-boot應用程式提供了預設的json轉換器,為Jackson。示例:pom.xml中dependency配置:<project x

Android JSON解析(JSONObject的使用)

    在沒有了解Android之前,以為跟C++一樣,解析json資料都是外部開源庫來處理的,但是Android自帶就有json解析器!言歸正傳,使用Android原生的Json解析器來解析json資料,這裡只跟大家提及需要注意的一點:使用JSONObject時,需要加上t

模板引擎:二、實現一個Json解析

2.Js實現Json解析器 前言 本文主要對Json解析器的實現進行探討。 如果想深入瞭解其原理,可以參考上一篇文章:模板引擎:一、理解Json解析器工作原理 案例說明 例如:拿一段最簡單的Json字串舉例(“{ “a”: 1

IT民工——發一個萬能的JSON解析吧!

using System;using System.Collections.Generic;using System.Text;namespace Pixysoft.Json{    publicclass CommonJsonModel : CommonJsonModelAnalyzer    {     

如何編寫一個JSON解析

編寫一個JSON解析器實際上就是一個函式,它的輸入是一個表示JSON的字串,輸出是結構化的對應到語言本身的資料結構。 和XML相比,JSON本身結構非常簡單,並且僅有幾種資料型別,以Java為例,對應的資料結構是: "string":Java的 String ;number:Java的 Long 或 D

Spring MVC4設定使用fastjson作為json解析,替代jackson

不論是效能、易用性、特性支援,fastjson都要遠好於預設的jackson,所以如果應用程式經常使用ajax進行資料互動,建議用fastjson作為預設解析器,官網:www.fhadmin.org只需要簡單配置:  <mvc:annotation-driven>    <mvc:mes

用ExpressionTree實現JSON解析

  今年的春節與往年不同,對每個人來說都是刻骨銘心的。突入其來的新型冠狀病毒使大家過上了“夢想”中的生活:吃了睡,睡了吃,還不用去公司上班,如今這樣的生活就在我們面前,可一點都不踏實,只有不停的學習才能讓人安心。於是我把年前弄了一點的JSON解析器實現了一下,序列化/反序列化物件轉換這部分主要用到了Expre

面試題|手寫JSON解析

這周的 Cassidoo 的每週簡訊有這麼一個面試題:: 寫一個函式,這個函式接收一個正確的 JSON 字串並將其轉化為一個物件(或字典,對映等,這取決於你選擇的語言)。示例輸入: fakeParseJSON('{ "data": { "fish": &quo

用c#自己實現一個簡單的JSON解析

## 一、JSON格式介紹 * JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。相對於另一種資料交換格式 XML,JSON 有著很多優點。例如易讀性更好,佔用空間更少等。在 web 應用開發領域內,得益於 JavaScript 對 JSON 提供的良好支援,JSO

手寫Json解析學習心得

![噢~從"{"開始,看來是個物件了!](https://mmbiz.qpic.cn/mmbiz_png/4Kicia369ptWGnwyBS6byzsaibkTuvBG6lYJKXfp7jhicjUiby1WoBswWLvAvAldDwmia0zvlAVfgOUT3wk6u1DLyVOQ/0?wx_fmt=

rest-Assured-解析json錯誤-需使用預定義的解析解析

resp json cati something 1.5.0 cte hat code itl 報錯信息: java.lang.IllegalStateException: Expected response body to be verified as JSON, HTM

開源nlohmann json解析庫詳解

nlohmann庫是C++解析json的庫,庫使用很簡單。環境使用linux+kdevelop即可,程式中使用nlohmann僅需要將json.hpp新增到工程中即可。 介紹一下相關函式的使用。 json j_object = {{"one", 1}, {"two", 2}}; 查詢key:

Json解析與序列化

從頭說起: 首先的首先,什麼是Json:一種資料表示形式,JSON:JavaScript Object Notation物件表示法 Json語法規則: 資料在鍵值對中 資料由逗號分隔 花括號儲存物件 方括號儲存陣列 像這樣: { "firstName":"J