flutter string 轉(zhuǎn) 字典

很難想象一個(gè)移動(dòng)應(yīng)用程序不需要與Web服務(wù)器通信或在某些時(shí)候容易存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)预伺。制作網(wǎng)絡(luò)連接的應(yīng)用程序時(shí)将塑,遲早需要消耗一些好的舊JSON禾唁。

本指南介紹了如何在Flutter中使用JSON曙强。它涵蓋了在不同場景中使用哪種JSON解決方案救湖,以及原因。

哪種JSON序列化方法適合我晾咪?

本文介紹了使用JSON的兩種常規(guī)策略:

  • 手動(dòng)序列化
  • 使用代碼生成進(jìn)行自動(dòng)序列化

不同的項(xiàng)目具有不同的復(fù)雜性和用例收擦。對(duì)于較小的概念驗(yàn)證項(xiàng)目或快速原型,使用代碼生成器可能過度谍倦。對(duì)于具有更多復(fù)雜性的多個(gè)JSON模型的應(yīng)用程序塞赂,手動(dòng)編碼很快就會(huì)變得乏味,重復(fù)昼蛀,并且適用于許多小錯(cuò)誤宴猾。

對(duì)較小的項(xiàng)目使用手動(dòng)序列化

手動(dòng)JSON解碼是指使用內(nèi)置的JSON解碼器 dart:convert圆存。它涉及將原始JSON字符串傳遞給json.decode() 方法,然后Map<String, dynamic> 在方法返回時(shí)查找所需的值仇哆。它沒有外部依賴性或特定的設(shè)置過程沦辙,它有利于快速驗(yàn)證概念。

當(dāng)項(xiàng)目變大時(shí)讹剔,手動(dòng)解碼效果不佳油讯。手動(dòng)編寫解碼邏輯可能變得難以管理且容易出錯(cuò)。如果在訪問不存在的JSON字段時(shí)出現(xiàn)拼寫錯(cuò)誤延欠,則代碼會(huì)在運(yùn)行時(shí)拋出錯(cuò)誤陌兑。

如果您的項(xiàng)目中沒有很多JSON模型,并且希望快速測試概念由捎,那么手動(dòng)序列化可能就是您想要的方式兔综。有關(guān)手動(dòng)編碼的示例,請(qǐng)參閱 使用dart:convert手動(dòng)序列化JSON狞玛。

使用代碼生成中大型項(xiàng)目

使用代碼生成的JSON序列化意味著使用外部庫為您生成編碼樣板软驰。進(jìn)行一些初始設(shè)置后,您將運(yùn)行一個(gè)文件監(jiān)視器心肪,從您的模型類生成代碼碌宴。例如, json_serializablebuilt_value 就是這些類型的庫蒙畴。

這種方法適用于較大的項(xiàng)目。不需要手寫的樣板文件呜象,并且在編譯時(shí)捕獲訪問JSON字段時(shí)的拼寫錯(cuò)誤膳凝。代碼生成的缺點(diǎn)是它需要一些初始設(shè)置。此外恭陡,生成的源文件可能會(huì)在項(xiàng)目導(dǎo)航器中產(chǎn)生視覺混亂蹬音。

當(dāng)您擁有中型或大型項(xiàng)目時(shí),您可能希望使用生成的代碼進(jìn)行JSON序列化休玩。要查看基于JSON編碼的代碼生成示例著淆,請(qǐng)參閱 使用代碼生成庫序列化JSON

Flutter中是否有GSON / Jackson / Moshi等價(jià)物拴疤?

簡單回答是不永部。

這樣的庫需要使用運(yùn)行時(shí)反射,這在Flutter中被禁用呐矾。運(yùn)行時(shí)反射會(huì)干擾樹抖動(dòng)苔埋,Dart已經(jīng)支持了很長時(shí)間。在樹搖動(dòng)的情況下蜒犯,您可以從發(fā)布版本中“擺脫”未使用的代碼组橄。這顯著優(yōu)化了應(yīng)用程序的大小荞膘。

由于反射使得默認(rèn)情況下隱式使用所有代碼,因此使樹難以振動(dòng)玉工。這些工具無法知道運(yùn)行時(shí)哪些部分未使用羽资,因此冗余代碼很難剝離。使用反射時(shí)遵班,應(yīng)用程序大小無法輕松優(yōu)化屠升。

** dartson怎么樣?**

dartson庫使用運(yùn)行時(shí)反射费奸,這使得它不兼容flutter弥激。

雖然您不能在Flutter中使用運(yùn)行時(shí)反射,但是某些庫為您提供了類似的易用API愿阐,而是基于代碼生成微服。代碼生成庫部分更詳細(xì)地介紹了此方法。

使用dart:convert手動(dòng)序列化JSON

Flutter中的基本JSON編碼非常簡單缨历。Flutter有一個(gè)內(nèi)置 dart:convert庫以蕴,包括一個(gè)簡單的JSON編碼器和解碼器。

以下是簡單用戶模型的示例JSON辛孵。

{
  "name": "John Smith",
  "email": "john@example.com"
}

有了dart:convert丛肮,您可以通過兩種方式對(duì)此JSON模型進(jìn)行編碼。

序列化JSON內(nèi)聯(lián)

通過查看dart:轉(zhuǎn)換JSON文檔魄缚,您將看到可以通過調(diào)用json.decode方法解碼JSON 宝与,并使用JSON字符串作為方法參數(shù)。

Map<String, dynamic> user = json.decode(json);

print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');

不幸的是冶匹,json.decode()只返回a Map<String, dynamic>习劫,這意味著在運(yùn)行時(shí)之前您不知道值的類型。使用這種方法嚼隘,您將丟失大多數(shù)靜態(tài)類型語言功能:類型安全性诽里,自動(dòng)完成以及最重要的編譯時(shí)異常。您的代碼將立即變得更容易出錯(cuò)飞蛹。

例如谤狡,無論何時(shí)訪問nameemail字段,都可能會(huì)快速引入拼寫錯(cuò)誤卧檐。由于JSON存在于地圖結(jié)構(gòu)中墓懂,編譯器不知道的拼寫錯(cuò)誤。

在模型類中序列化JSON

通過引入User在此示例中調(diào)用的普通模型類來對(duì)抗前面提到的問題泄隔。在User課堂上拒贱,你會(huì)發(fā)現(xiàn):

  • 一個(gè)User.fromJson構(gòu)造函數(shù),構(gòu)造一個(gè)新的User從地圖結(jié)構(gòu)實(shí)例。
  • 一種toJsonUser實(shí)例轉(zhuǎn)換為地圖的方法逻澳。

使用這種方法闸天,調(diào)用代碼可以具有類型安全性,nameemail字段的自動(dòng)完成以及編譯時(shí)異常斜做。如果您使用拼寫錯(cuò)誤或?qū)⒆侄我暈?code>ints而不是Strings苞氮,則應(yīng)用程序?qū)o法編譯,而不是在運(yùn)行時(shí)崩潰瓤逼。

user.dart

class User {
  final String name;
  final String email;

  User(this.name, this.email);

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'];

  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'email': email,
    };
}

解碼邏輯的責(zé)任現(xiàn)在在模型本身內(nèi)部移動(dòng)笼吟。使用這種新方法,您可以輕松解碼用戶霸旗。

Map userMap = json.decode(json);
var user = new User.fromJson(userMap);

print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');

要對(duì)用戶進(jìn)行編碼贷帮,請(qǐng)將User對(duì)象傳遞給json.encode方法。您不需要調(diào)用該toJson方法诱告,因?yàn)?code>json.encode 已經(jīng)為您完成了撵枢。

String json = json.encode(user);

使用這種方法,調(diào)用代碼根本不必?fù)?dān)心JSON序列化精居。但是锄禽,模型類仍然必須。在生產(chǎn)應(yīng)用程序中靴姿,您需要確保序列化正常工作沃但。在實(shí)踐中,這些User.fromJsonUser.toJson 方法都需要進(jìn)行單元測試以驗(yàn)證正確的行為佛吓。

但是宵晚,現(xiàn)實(shí)場景通常不那么簡單。您不太可能使用如此小的JSON響應(yīng)维雇。嵌套的JSON對(duì)象也是常用的坝疼。

如果有一些東西可以為您處理JSON編碼和解碼,那就太好了谆沃。幸運(yùn)的是,有仪芒!

使用代碼生成庫序列化JSON

雖然還有其他庫可用唁影,但本指南使用 json_serializable包,這是一個(gè)自動(dòng)生成的源代碼生成器掂名,可為您生成JSON序列化樣板据沈。

由于序列化代碼不再是手動(dòng)或手動(dòng)維護(hù)的,因此可以最大限度地降低在運(yùn)行時(shí)出現(xiàn)JSON序列化異常的風(fēng)險(xiǎn)饺蔑。

在項(xiàng)目中設(shè)置json_serializable

要包含json_serializable在項(xiàng)目中锌介,您需要一個(gè)常規(guī)依賴項(xiàng)和兩個(gè)dev依賴項(xiàng)。簡而言之,dev依賴項(xiàng) 是我們的應(yīng)用程序源代碼中未包含的依賴項(xiàng) - 它們僅在開發(fā)環(huán)境中使用孔祸。

可以通過遵循 JSON可序列化示例中的pubspec文件來查看這些必需依賴項(xiàng)的最新版本 隆敢。

pubspec.yaml

dependencies:
  # Your other regular dependencies here
  json_annotation: ^2.0.0

dev_dependencies:
  # Your other dev_dependencies here
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

flutter packages get在項(xiàng)目根文件夾中運(yùn)行(或單擊 編輯器中的Packages Get)以在項(xiàng)目中使用這些新的依賴項(xiàng)。

以json_serializable方式創(chuàng)建模型類
以下顯示如何將User類轉(zhuǎn)換為一個(gè)類json_serializable 崔慧。為簡單起見拂蝎,此代碼使用先前示例中的簡化JSON模型。

user.dart

class User {
  final String name;
  final String email;

  User(this.name, this.email);

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'];

  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'email': email,
    };
}

采用這種設(shè)置惶室,源代碼生成器用于編碼和將編碼生成代碼nameemail從JSON字段温自。

如果需要,還可以輕松自定義命名策略皇钞。例如悼泌,如果API返回帶有snake_case的對(duì)象,并且您想在模型中使用 lowerCamelCase夹界,則可以使用@JsonKey帶有name參數(shù)的注釋:

/// Tell json_serializable that "registration_date_millis" should be
/// mapped to this property.
@JsonKey(name: 'registration_date_millis')
final int registrationDateMillis;

運(yùn)行代碼生成實(shí)用程序

json_serializable第一次創(chuàng)建類時(shí)馆里,您將收到類似于下圖所示的錯(cuò)誤。

當(dāng)模型類的生成代碼尚不存在時(shí)掉盅,IDE警告也拜。

這些錯(cuò)誤完全正常,僅僅是因?yàn)槟P皖惖纳纱a尚不存在趾痘。要解決此問題慢哈,請(qǐng)運(yùn)行生成序列化樣板的代碼生成器。

有兩種運(yùn)行代碼生成器的方法永票。

一次性代碼生成

通過flutter packages pub run build_runner build在項(xiàng)目根目錄中運(yùn)行卵贱,可以在需要時(shí)為模型生成JSON序列化代碼。這會(huì)觸發(fā)一次性構(gòu)建侣集,該構(gòu)建遍歷源文件键俱,選擇相關(guān)文件,并為它們生成必要的序列化代碼世分。

雖然這很方便编振,但如果您不必每次在模型類中進(jìn)行更改時(shí)都必須手動(dòng)運(yùn)行構(gòu)建,那將是很好的臭埋。

不斷生成代碼

一個(gè)觀察者踪央,使我們的源代碼生成的過程更加方便。它會(huì)監(jiān)視項(xiàng)目文件中的更改瓢阴,并在需要時(shí)自動(dòng)構(gòu)建必要的文件畅蹂。通過flutter packages pub run build_runner watch在項(xiàng)目根目錄中運(yùn)行來啟動(dòng)觀察程序 。

啟動(dòng)觀察者一次并讓它在后臺(tái)運(yùn)行是安全的荣恐。

使用json_serializable模型

要以這種json_serializable方式解碼JSON字符串液斜,您實(shí)際上沒有對(duì)我們以前的代碼進(jìn)行任何更改累贤。

Map userMap = json.decode(json);
var user = User.fromJson(userMap);

編碼也是如此。調(diào)用API與以前相同少漆。

String json = json.encode(user);

有了json_serializable臼膏,您可以忘記User該類中的任何手動(dòng)JSON序列化 。源代碼生成器創(chuàng)建一個(gè)名為的文件user.g.dart检疫,該文件具有所有必需的序列化邏輯讶请。您不再需要編寫自動(dòng)化測試來確保序列化工作 - 現(xiàn)在圖書館有責(zé)任確保序列化正常工作。

進(jìn)一步參考

有關(guān)更多信息屎媳,請(qǐng)參閱以下資源:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夺溢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子烛谊,更是在濱河造成了極大的恐慌风响,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丹禀,死亡現(xiàn)場離奇詭異状勤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)双泪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門持搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人焙矛,你說我怎么就攤上這事葫盼。” “怎么了村斟?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵贫导,是天一觀的道長。 經(jīng)常有香客問我蟆盹,道長孩灯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任逾滥,我火速辦了婚禮峰档,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寨昙。我一直安慰自己面哥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布毅待。 她就那樣靜靜地躺著,像睡著了一般归榕。 火紅的嫁衣襯著肌膚如雪尸红。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音外里,去河邊找鬼怎爵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛盅蝗,可吹牛的內(nèi)容都是我干的鳖链。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼墩莫,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼芙委!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起狂秦,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤灌侣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后裂问,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侧啼,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年堪簿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痊乾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡椭更,死狀恐怖哪审,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甜孤,我是刑警寧澤协饲,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站缴川,受9級(jí)特大地震影響茉稠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜把夸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一而线、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恋日,春花似錦膀篮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谈截,卻和暖如春筷屡,著一層夾襖步出監(jiān)牢的瞬間涧偷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工毙死, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燎潮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓扼倘,卻偏偏與公主長得像确封,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子再菊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容