什麼是 JSON 以及如何使用它?

已發表: 2022-08-14
覆蓋在計算機顯示器上的“JSON”文本圖像
瑪麗亞沃諾特納/Shutterstock.com

JSON(JavaScript Object Notation)是一種用於表示結構化數據的標準化格式。 儘管 JSON 從 JavaScript 編程語言發展而來,但它現在已成為系統間數據交換的普遍方法。 大多數現代 API 接受 JSON 請求並發出 JSON 響應,因此對格式及其功能有很好的工作知識很有用。

在本文中,我們將解釋 JSON 是什麼,它如何表達不同的數據類型,以及在流行的編程語言中生成和使用它的方式。 我們還將介紹 JSON 的一些限制以及已經出現的替代方案。

JSON基礎

JSON 最初是由 Douglas Crockford 設計的,作為一種無狀態格式,用於在瀏覽器和服務器之間進行數據通信。 早在 2000 年代初期,網站開始在初始頁面加載後從其服務器異步獲取額外數據。 作為從 JavaScript 派生的基於文本的格式,JSON 使在這些應用程序中獲取和使用數據變得更加簡單。 該規範最終在 2013 年被標準化為 ECMA-404。

JSON 始終作為字符串傳輸。 這些字符串可以解碼為一系列基本數據類型,包括數字、布爾值、數組和對象。 這意味著可以在傳輸過程中保留對象層次結構和關係,然後在接收端以適合編程環境的方式重新組裝。

一個基本的 JSON 示例

這是一篇博文的 JSON 表示:

 {
    “身份證”:1001,
    "title": "什麼是 JSON?",
    “作者”: {
        “身份證”:1,
        “名稱”:“詹姆斯沃克”
    },
    “標籤”:[“api”,“json”,“編程”],
    “已發布”:錯誤,
    “已發佈時間戳”:空
}

此示例演示了所有 JSON 數據類型。 它還說明了 JSON 格式數據的簡潔性,這是使其在 API 中使用如此吸引人的特徵之一。 此外,與 XML 等更冗長的格式不同,JSON 相對容易按原樣閱讀。

JSON 數據類型

六種類型的數據可以在 JSON 中原生表示:

  • 字符串——字符串寫在雙引號之間; 字符可以使用反斜杠進行轉義。
  • 數字——數字寫成不帶引號的數字。 您可以包含一個小數部分來表示一個浮點數。 大多數 JSON 解析實現在不存在小數點時假定為整數。
  • 布爾值 – 支持文字值truefalse
  • Nullnull文字值可用於表示空值或省略值。
  • 數組——數組是用方括號表示的簡單列表。 列表中的每個元素都用逗號分隔。 數組可以包含任意數量的項目,並且可以使用所有支持的數據類型。
  • 對象——對象由大括號創建。 它們是鍵值對的集合,其中鍵是字符串,用雙引號括起來。 每個鍵都有一個可以採用任何可用數據類型的值。 您可以嵌套對像以創建級聯層次結構。 每個值後面必須有一個逗號,表示該鍵值對的結束。

JSON 解析器會自動將這些數據類型轉換為適合其語言的結構。 例如,您不需要手動將id轉換為整數。 解析整個 JSON 字符串足以將值映射回其原始數據格式。

語義和驗證

在對數據進行編碼時,JSON 有一些需要遵守的規則。 不符合語法的字符串將無法被消費者解析。

特別重要的是要注意字符串和對象鍵周圍的引號。 您還必須確保在對像或數組中的每個條目之後使用逗號。 但是,JSON不允許在最後一個條目之後使用尾隨逗號——無意中包含一個逗號是導致驗證錯誤的常見原因。 大多數文本編輯器會為您突出顯示語法問題,幫助發現錯誤。

儘管有這些常見的轉折點,但 JSON 是最容易手動編寫的數據格式之一。 大多數人一旦熟悉了語法,就會發現它既快捷又方便。 總體而言,JSON 往往比 XML 更不容易出錯,其中不匹配的開始和結束標記、無效的模式聲明和字符編碼問題通常會導致問題。

指定 JSON 內容

當 JSON 保存到文件時,通常使用.json擴展名。 JSON 內容具有標準化的 MIME 類型application/json ,儘管出於兼容性原因有時使用text/json 。 現在,您應該依賴application/json來獲取AcceptContent-Type HTTP 標頭。

大多數使用 JSON 的 API 會將所有內容封裝在頂級對像中:

 {
    “錯誤”:1000
}

但這不是必需的——文字類型作為文件中的頂級節點是有效的,因此以下示例也是有效的 JSON:

 1000 
 真的
 無效的

它們將在您的編程語言中解碼為各自的標量。

使用 JSON

大多數編程語言都有內置的 JSON 支持。 下面介紹瞭如何在一些流行的環境中與 JSON 數據進行交互。

JavaScript

在 JavaScript 中JSON.stringify()JSON.parse()方法用於編碼和解碼 JSON 字符串:

 常量帖子= {
    編號 1001 
    標題 “什麼是 JSON?” ,
    作者 {
        編號 1 
        名稱 “詹姆斯沃克”
    }
} ;

常量編碼Json = JSON。 字符串化發布 

// {"id": 1001, "title": "什麼是 JSON?", ...}
安慰。 日誌編碼的Json  

常量解碼Json = JSON。 解析編碼Json  

//詹姆斯沃克
安慰。 日誌 decodedJson.author.name   _

PHP

PHP 中的等效函數是json_encode()json_decode()

 $帖子= [
    "id" => 1001 ,
    “標題” => “什麼是 JSON?” ,
    “作者” => [
        "id" => 1 ,
        “名字” => “詹姆斯沃克”
    ]
] ;

$encodedJson = json_encode ( $post ) ;

// {"id": 1001, "title": "什麼是 JSON?", ...}
迴聲$encodedJson ;

$decodedJson = json_decode ( $encodedJson , true ) ;

//詹姆斯沃克
echo $decodedJson [ "作者" ] [ "名稱" ] ;

Python

Python 提供json.dumps()json.loads()分別進行序列化和反序列化:

 導入json

帖子= {
    “身份證”1001 
    "title" : "什麼是 JSON?" ,
    “作者”{
        “身份證”1 
        “名稱”“詹姆斯沃克”
    }
}

編碼的JSON = json。 轉儲帖子

# {"id": 1001, "title": "什麼是 JSON?", ...}
打印編碼的Json 

解碼的Json = json。 加載編碼的Json 

#詹姆斯沃克
打印 decodedJson [ “作者” ] [ “名稱” ] 

紅寶石

Ruby 提供JSON.generateJSON.parse

 需要“json”

帖子 = {
    "id" => 1001 ,
    “標題” => “什麼是 JSON?” ,
    “作者” => {
        "id" => 1 ,
        “名字” => “詹姆斯沃克”
    }
}

編碼的JSON = JSON。 生成發布

# {"id": 1001, "title": "什麼是 JSON?", ...}
編碼的Json

解碼的JSON = JSON。 解析編碼的Json 

#詹姆斯沃克
decodedJson [ “作者” ] [ “名稱” ]

JSON 限制

JSON 是一種輕量級格式,專注於在數據結構中傳達值。 這使得它可以快速解析並且易於使用,但也意味著存在可能導致挫折的缺點。 以下是一些最大的問題。

暫無評論

JSON 數據不能包含評論。 缺少註釋會降低清晰度並迫使您將文檔放在其他地方。 這可能使 JSON 不適合諸如配置文件之類的情況,在這些情況下修改不頻繁並且字段的目的可能不清楚。

沒有模式

JSON 不允許您為數據定義模式。 例如,沒有辦法強制id是必需的整數字段。 這可能會導致無意中出現格式錯誤的數據結構。

沒有參考

字段不能引用數據結構中的其他值。 這通常會導致重複增加文件大小。 回到前面的博客文章示例,您可以有一個博客文章列表,如下所示:

 {
    “帖子”:[
        {
            “身份證”:1001,
            "title": "什麼是 JSON?",
            “作者”: {
                “身份證”:1,
                “名稱”:“詹姆斯沃克”
            }
        },
        {
            “身份證”:1002,
            "title": "什麼是 SaaS?",
            “作者”: {
                “身份證”:1,
                “名稱”:“詹姆斯沃克”
            }
        }
    ]
}

兩篇文章的作者相同,但與該對象相關的信息必須重複。 在理想情況下,JSON 解析器實現將能夠從類似於以下的輸入生成上面顯示的結構:

 {
    “帖子”:[
        {
            “身份證”:1001,
            "title": "什麼是 JSON?",
            “作者”:“{{ .authors.james }}”
        },
        {
            “身份證”:1002,
            "title": "什麼是 SaaS?",
            “作者”:“{{ .authors.james }}”
        }
    ],
    “作者”:{
        “詹姆士”: {
            “身份證”:1,
            “名稱”:“詹姆斯沃克”
        }
    }
}

目前,標準 JSON 無法做到這一點。

沒有高級數據類型

六種支持的數據類型省略了許多常見類型的值。 JSON 本身無法存儲日期、時間或地理位置點,因此您需要自行決定此信息的格式。

這會導致不方便的差異和極端情況。 如果您的應用程序將時間戳作為字符串處理,例如2022-07-01T12:00:00+00:00 ,但外部 API 將時間顯示為 Unix 紀元後的秒數 – 1657287000 – 您需要記住何時使用每個格式。

JSON 替代品

YAML 是領先的 JSON 替代方案。 它是格式的超集,具有更易於閱讀的表示、自定義數據類型和對引用的支持。 它旨在解決與 JSON 相關的大多數可用性挑戰。

YAML 已在配置文件以及 DevOps、IaC 和可觀察性工具中得到廣泛採用。 它很少用作 API 的數據交換格式。 YAML 的相對複雜性意味著它對新手來說不太容易接近。 小的語法錯誤可能會導致令人困惑的解析失敗。

協議緩衝區(protobufs)是另一個新興的 JSON 競爭者,旨在序列化結構化數據。 Protobuf 具有數據類型聲明、必填字段和對大多數主要編程語言的支持。 作為通過網絡傳輸數據的更有效方式,該系統越來越受歡迎。

概括

JSON 是一種基於文本的數據表示格式,可以對六種不同的數據類型進行編碼。 JSON 已成為軟件開發生態系統的主要內容; 它受到所有主要編程語言的支持,並已成為過去幾十年開發的大多數 REST API 的默認選擇。

雖然 JSON 的簡單性是其受歡迎的一部分,但它也限制了您可以使用該格式實現的目標。 缺乏對模式、註釋、對象引用和自定義數據類型的支持意味著一些應用程序會發現它們超出了 JSON 所能提供的範圍。 YAML 和 Protobuf 等較年輕的替代方案有助於解決這些挑戰,而 XML 仍然是想要定義數據模式並且不介意冗長的應用程序的競爭者。