Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 19, 2022 08:06 pm GMT

Dart/Flutter da Json Ayrtrma

JSON'u ayrtrmak, nternet'ten veri almas gereken uygulamalar iin ok yaygn bir grevdir.

Ne kadar JSON verisi ilemeniz gerektiine bal olarak iki seeneiniz vardr:

  1. Tm JSON ayrtrma kodunu manuel olarak yazn
  2. Kod oluturma ile sreci otomatikletirin

Bu klavuz, aadakiler dahil olmak zere JSON'un Dart koduna manuel olarak nasl ayrtrlacana odaklanacaktr :

JSON encoding (kodlama) ve decoding (kod zme)
Type-safe (tip gvenli) model snflar tanmlama
Factory cunstructor kullanarak JSON'u Dart koduna ayrtrma
Nullable/optional (null yaplabilir/istee bal) deerlerle almak
Data validation (veri dorulama)
JSON serializing
Complex/nested (karmak/i ie) JSON verilerini ayrtrma
deep_pick paketinin kullanm

Bu makalenin sonunda, salam JSON ayrtrma ve dorulama koduyla model snflarnn nasl yazlacan reneceksiniz.

Ve bir sonraki makalede , tm ayrtrma kodunu elle yazmak zorunda kalmamak iin kod oluturma aralaryla (code generation tools) JSON ayrtrma hakknda bilgi edineceksiniz.

JSON Kodlama ve Kod zme (Encoding and Decoding JSON)

A zerinden bir JSON yant gnderildiinde, ykn tamam bir dize olarak kodlanr .

Ancak Flutter uygulamalarmzn iinde, verileri bir dizeden manuel olarak karmak istemiyoruz:

final json = '{ "name": "Pizza da Mario", "cuisine": "Italian", "reviews": [{"score": 4.5,"review": "The pizza was amazing!"},{"score": 5.0,"review": "Very friendly staff, excellent service!"}]}';

Bunun yerine JSON'un kodunu zerek ierii okuyabiliyoruz .

JSON verilerini a zerinden gndermek iin nce kodlanmas (encoded) veya seriletirilmesi (serialized) gerekir . Kodlama , bir veri yapsn (data structure) bir string'e dntrme ilemidir . Ters ilem, decoding veya deserialization (seri durumdan karma) olarak adlandrlr . Dize olarak bir JSON yk aldnzda, kullanmadan nce kodunu zmeniz (decode) veya seri durumdan karmanz (deserialize) gerekir.

Dart ile JSON kodunu zme:dntrme (Decoding JSON with dart:convert)

Basit olmas iin, bu kk JSON ykn ele alalm:

//bu, adan aldmz baz yant verilerini temsil eder, rnein:// final response = await http.get(uri);// final jsonData = response.bodyfinal jsonData = '{ "name": "Pizza da Mario", "cuisine": "Italian" }';

indeki anahtarlar ve deerleri okumak iin nce dart:convert paketini kullanarak kodunu zmemiz gerekiyor

// 1. import dart:convertimport 'dart:convert';// bu, adan aldmz baz yant verilerini temsil ederfinal jsonData = '{ "name": "Pizza da Mario", "cuisine": "Italian" }';// 2. json kodunu zfinal parsedJson = jsonDecode(jsonData);// 3. tr ve deeri yazdrprint('${parsedJson.runtimeType} : $parsedJson');

Bu kodu altrrsak u kty alrz:

_InternalLinkedHashMap<String, dynamic> : {name: Pizza da Mario, cuisine: Italian}

Pratikte, sonu tr ile ayndr Map.

_InternalLinkedHashMap , srayla Map'i uygulayan LinkedHashMap'in zel bir uygulamasdr.

Bu nedenle, anahtarlar String ve deerler dynamic trndedir . Bu mantkldr nk her JSON deeri primitive type (ilkel bir tr => boolean/number/string) veya bir koleksiyon (list veya map) olabilir.

Aslnda, jsonDecode(), iinde ne olduuna baklmakszn herhangi bir geerli JSON yk zerinde alan genel bir yntemdir. Tek yapt, kodunu zmek ve dinamik bir deer dndrmek.

Ancak Dart'ta dinamik deerlerle alrsak, strong type-safety (gl tip gvenliinin) tm avantajlarn kaybederiz. ok daha iyi bir yaklam, duruma gre (on a case-by-case basis) yant verilerimizi temsil eden baz zel model snflar tanmlamaktr.

Dart statik olarak yazlm bir dil olduundan, JSON verilerini gerek dnya nesnelerini (yemek tarifi, alan vb.) temsil eden model snflarna dntrmek ve tr sisteminden (type system) en iyi ekilde yararlanmak nemlidir.

yleyse bunun nasl yaplacan grelim.

JSON'u bir Dart modeli snfna ayrtrma

Bu basit JSON verildiinde:

{  "name": "Pizza da Mario",  "cuisine": "Italian"}

Onu temsil edecek bir Restaurantsnf yazabiliriz:

class Restaurant {  Restaurant({required this.name, required this.cuisine});  final String name;  final String cuisine;}

Sonu olarak, verileri yle okumak yerine:

parsedJson['name']; // dynamicparsedJson['cuisine']; // dynamic

yle okuyabiliriz:

restaurant.name; //geersiz klnamaz, deimez bir string olmas garanti edilirrestaurant.cuisine; // geersiz klnamaz, deimez bir stringolmas garanti edilir

Bu ok daha temizdir ve derleme zaman gvenlii ( compile-time safety) elde etmek ve yazm hatalarn ve dier hatalardan kanmak iin tr sisteminden yararlanabiliriz.

Ancak, parsedJson'umuzu bir Restaurant nesnesine nasl dntreceimizi henz belirlemedik!

JSON da Dart'a Factory Constructor Ekleme

Bunu halletmek iin bir factory constructor tanmlayalm:

factory Restaurant.fromJson(Map<String, dynamic> data) {  // note the explicit cast to String  // this is required if robust lint rules are enabled  final name = data['name'] as String;  final cuisine = data['cuisine'] as String;  return Restaurant(name: name, cuisine: cuisine);}

Bir factory constructor, sonucu dndrmeden nce baz iler yapmamza (deikenler oluturma, baz dorulamalar gerekletirme) izin verdii iin JSON ayrtrmas (parsing) iin iyi bir seimdir . Bu, normal (generative-retken) constructor'larla mmkn deildir.

Constructor' u ekilde kullanabiliriz:

// type: Stringfinal jsonData = '{ "name": "Pizza da Mario", "cuisine": "Italian" }';// type: dynamic (runtime type: _InternalLinkedHashMap<String, dynamic>)final parsedJson = jsonDecode(jsonData);// type: Restaurantfinal restaurant = Restaurant.fromJson(parsedJson);

ok daha iyi. Artk kodumuzun geri kalan Restaurant class'n kullanabilir ve Dart'ta gl tip gvenliinin (type-safety) tm avantajlarn elde edebilir.

Bazen , belirli bir key/value iftine sahip olan veya olmayan baz JSON'lar ayrtrmamz gerekir .

rnein, bir restorann ilk ne zaman aldn bize bildiren istee bal bir alanmz olduunu varsayalm:

{  "name": "Ezo Sushi",  "cuisine": "Japanese",  "year_opened": 1990}

Year_opened alan istee balysa (optional), onu model snfmzda bo bir deikenle (nullable variable) temsil edebiliriz.

te Restaurant snf iin gncellenmi bir uygulama:

class Restaurant {  Restaurant({required this.name, required this.cuisine, this.yearOpened});  final String name; // non-nullable  final String cuisine; // non-nullable  final int? yearOpened; // nullable  factory Restaurant.fromJson(Map<String, dynamic> data) {    final name = data['name'] as String; // cast as non-nullable String    final cuisine = data['cuisine'] as String; // cast as non-nullable String    final yearOpened = data['year_opened'] as int?; // cast as nullable int    return Restaurant(name: name, cuisine: cuisine, yearOpened: yearOpened);  }}

Genel bir kural olarak, istee bal JSON deerlerini (optional JSON values) null yaplabilir Dart zelliklerine (nullable Dart properties) elemeliyiz . Alternatif olarak, bu rnekte olduu gibi, null yaplamayan Dart zelliklerini (non-nullable Dart properties) mantkl bir varsaylan deerle kullanabiliriz:

// note: all the previous properties have been omitted for simplicityclass Restaurant {  Restaurant({    // 1. required    required this.hasIndoorSeating,  });  // 2. *non-nullable*  final bool hasIndoorSeating;  factory Restaurant.fromJson(Map<String, dynamic> data) {    // 3. cast as *nullable* bool    final hasIndoorSeating = data['has_indoor_seating'] as bool?;    return Restaurant(      // 4. varsaylan bir dddeer atamak iin ?? operatrn kullanmak      hasIndoorSeating: hasIndoorSeating ?? true,    );  }}

Bu durumda, varsaylan bir deer salamak iin bo birletirme operatrn (null-coalescing operator) (??) nasl kullandmza dikkat edin.

Veri Dorulama

Factory constructor kullanmann bir yarar, gerekirse baz ek dorulamalar yapabilmemizdir.

rnein, gerekli bir deer eksikse UnsupportedError veren bir savunma kodu yazabiliriz.

factory Restaurant.fromJson(Map<String, dynamic> data) {  // casting as a nullable String so we can do an explicit null check  final name = data['name'] as String?;  if (name == null) {    throw UnsupportedError('Invalid data: $data -> "name" is missing');  }  final cuisine = data['cuisine'] as String?;  if (cuisine == null) {    throw UnsupportedError('Invalid data: $data -> "cuisine" is missing');  }  final yearOpened = data['year_opened'] as int?;  // Yukardaki if ifadeleri sayesinde, burada name ve cuisine deerlerinin  bo olmayaca garanti edilir.  return Restaurant(name: name, cuisine: cuisine, yearOpened: yearOpened);}

Genel olarak, her bir deer iin almak API tketicisi olarak bizim iimizdir:

tr (String, int, vb.)
istee balysa veya deilse (nullable vs non-nullable)
hangi deer aralna izin verilirse

Bu, JSON ayrtrma kodumuzu daha salam hale getirecektir. Ve tm dorulamalar nceden yapldndan , widget snflarmzda geersiz verilerle uramak zorunda kalmayacaz .

toJson() ile JSON Seriletirme

JSON'u ayrtrmak yararldr, ancak bazen bir model nesnesini JSON'a geri dntrmek ve a zerinden gndermek isteriz.

Bunu yapmak iin Restaurant snfmz iin bir toJson() yntemi tanmlayabiliriz:

// note the return typeMap<String, dynamic> toJson() {  // return a map literal with all the non-null key-value pairs  return {    'name': name,    'cuisine': cuisine,    if (yearOpened != null) 'year_opened': yearOpened,  };}

Ve bunu yle kullanabiliriz:

// bir Restoran nesnesi verildifinal restaurant = Restaurant(name: "Patatas Bravas", cuisine: "Spanish");// convert it to mapfinal jsonMap = restaurant.toJson();// onu bir JSON dizgisine kodlafinal encodedJson = jsonEncode(jsonMap);// sonra herhangi bir a paketiyle istek gvdesi olarak gnder

e JSON' Ayrtrma: List of Map

Artk JSON ayrtrma ve dorulamann temellerini anladmza gre, ilk rneimize geri dnelim ve nasl ayrtrlacan grelim:

{  "name": "Pizza da Mario",  "cuisine": "Italian",  "reviews": [    {      "score": 4.5,      "review": "The pizza was amazing!"    },    {      "score": 5.0,      "review": "Very friendly staff, excellent service!"    }  ]}

Model snflarn ve tip gvenliini (type-safety) sonuna kadar kullanmak istiyoruz, bu yzden bir Review snf tanmlayalm:

class Review {  Review({required this.score, this.review});  // non-nullable - puan alannn her zaman mevcut olduu varsaylr  final double score;  // nullable - inceleme alannn istee bal olduunu varsayarsak  final String? review;  factory Review.fromJson(Map<String, dynamic> data) {    final score = data['score'] as double;    final review = data['review'] as String?;    return Review(score: score, review: review);  }  Map<String, dynamic> toJson() {    return {      'score': score,      // burada, null deerleri hesaba katmak iin collection-if kullanyoruz      if (review != null) 'review': review,    };  }}

Ardndan, bir reviews listesi eklemek iin Restoran class'n gncelleyebiliriz:

class Restaurant {  Restaurant({    required this.name,    required this.cuisine,    this.yearOpened,    required this.reviews,  });  final String name;  final String cuisine;  final int? yearOpened;  final List<Review> reviews;}

Ayrca factory cunstructor'n da gncelleyebiliriz:

factory Restaurant.fromJson(Map<String, dynamic> data) {  final name = data['name'] as String;  final cuisine = data['cuisine'] as String;  final yearOpened = data['year_opened'] as int?;  // reviews eksik olabileceinden null yaplabilir bir listeye dntrn  final reviewsData = data['reviews'] as List<dynamic>?;  // reviews eksik deilse  final reviews = reviewsData != null      // her review'i  bir Review object'e eleyin      ? reviewsData.map((reviewData) => Review.fromJson(reviewData))        // map() yinelenebilir bir deer dndrr bylece onu listeye evirebiliriz        .toList()      // geri dn deeri olarak bo bir liste kullann      : <Review>[];  // tm argmanlar geen sonucu dndr  return Restaurant(    name: name,    cuisine: cuisine,    yearOpened: yearOpened,    reviews: reviews,  );}

reviews eksik olabilir, bu nedenle nullable bir Listeye yaynlyoruz.
listedeki deerlerin herhangi bir tr olabilir, bu nedenle List kullanyoruz.
Review.fromJson() kullanarak her dinamik deeri bir Review nesnesine dntrmek iin .map() operatrn kullanrz.
reviews eksikse, yedek olarak bo bir liste ([]) kullanrz.

Bu zel uygulama, neyin bo olup olmayaca, hangi yedek deerlerin kullanlaca vb. hakknda baz varsaymlarda bulunur. Kullanm durumunuz iin en uygun ayrtrma kodunu yazmanz gerekir.

e (Nested) Modelleri Seriletirme

Son adm olarak, bir Restoran tekrar Map'e dntrmek iin toJson() yntemini burada bulabilirsiniz:

Map<String, dynamic> toJson() {  return {    'name': name,    'cuisine': cuisine,    if (yearOpened != null) 'year_opened': yearOpened,    'reviews': reviews.map((review) => review.toJson()).toList(),  };}

Tm i ie deerleri de seriletirmemiz gerektiinden (yalnzca Restaurant snfnn kendisini deil) List esini nasl List>'e dntrdmze dikkat edin.

Yukardaki kod ile bir Restaurant nesnesi oluturup onu tekrar kodlanp yazdrlabilen veya a zerinden gnderilebilen bir map'e dntrebiliriz:

final restaurant = Restaurant(  name: 'Pizza da Mario',  cuisine: 'Italian',  reviews: [    Review(score: 4.5, review: 'The pizza was amazing!'),    Review(score: 5.0, review: 'Very friendly staff, excellent service!'),  ],);final encoded = jsonEncode(restaurant.toJson());print(encoded);// output: {"name":"Pizza da Mario","cuisine":"Italian","reviews":[{"score":4.5,"review":"The pizza was amazing!"},{"score":5.0,"review":"Very friendly staff, excellent service!"}]}

Derin Deerler (Deep Values) Semek

Tm bir JSON belgesini type-safe model snflarna ayrtrmak ok yaygn bir kullanm durumudur.

Ancak bazen derinden i ie (deeply nested) olabilecek baz belirli deerleri okumak isteriz.

rnek JSON'umuzu bir kez daha ele alalm:

{  "name": "Pizza da Mario",  "cuisine": "Italian",  "reviews": [    {      "score": 4.5,      "review": "The pizza was amazing!"     },    {      "score": 5.0,      "review": "Very friendly staff, excellent service!"    }  ]}

reviews listesindeki ilk score deerini almak isteseydik yle yazardk:

final decodedJson = jsonDecode(jsonData); // dynamicfinal score = decodedJson['reviews'][0]['score'] as double;

Bu geerli Dart kodudur nk decodedJson deikeni dinamiktir ve onunla birlikte indis operatrn kullanabiliriz ([]).

Ancak yukardaki kod ne null safe ne de type safe ve ayrtrlan deeri aka istediimiz tre (double) evirmemiz gerekiyor.

Bunu nasl iyiletirebiliriz?

deep_pick Paketi

Deep_pick paketi, tr asndan type-safe API ile JSON parsing'i basitletirir.

import 'dart:convert';import 'package:deep_pick/deep_pick.dart';final decodedJson = jsonDecode(jsonData); // dynamicfinal score = pick(decodedJson, 'reviews', 0, 'score').asDoubleOrThrow();

deep_pick, ilkel trleri (primitive types), listeleri, mapleri, DateTime nesnelerini ve daha fazlasn ayrtrmak iin kullanabileceimiz eitli esnek API'ler sunar.

toString() yntemi ekleme

Model snflaryla alrken, konsola kolayca yazdrlabilmeleri iin bir toString() yntemi salamak ok yararldr.

Zaten bir toJson() yntemimiz olduundan, onu u ekilde kullanabiliriz:

@overrideString toString() => toJson().toString();

Sonu olarak, restoranmz dorudan u ekilde yazdrabiliriz:

print(restaurant);// output: {name: Pizza da Mario, cuisine: Italian, reviews: [{score: 4.5, review: The pizza was amazing!}, {score: 5.0, review: Very friendly staff, excellent service!}]}

Performans Hakknda Not

Kk JSON belgelerini ayrtrdnzda, uygulamanzn yant vermeye devam etmesi ve performans sorunlar yaamamas muhtemeldir.

Ancak ok byk JSON belgelerinin ayrtrlmas, arka planda en iyi ekilde ayr bir Dart isolate zerinde yaplan pahal hesaplamalara neden olabilir . Resmi belgelerin bu konuda iyi bir klavuzu var:
JSON'u arka planda ayrtrn

zm

JSON seriletirme ok sradan bir itir. Ancak uygulamalarmzn doru almasn istiyorsak, bunu doru yapmamz ve ayrntlara dikkat etmemiz ok nemlidir:

JSON verilerini seri hale getirmek iin 'dart:convert' esinden jsonEncode() ve jsonDecode() kullann

Uygulamanzdaki tm alana zg (domain-specific) JSON nesneleri iin fromJson() ve toJson() ile model snflar oluturun

Ayrtrma kodunu daha salam hale getirmek iin fromJson() iine explicit casts, validation ve bo denetimler(null checks) ekleyin

ie (nested) JSON verileri (list of maps) iin fromJson() ve toJson() yntemlerini uygulayn

JSON'u tr asndan gvenli(type-safe) bir ekilde ayrtrmak (parse) iin deep_pick paketini kullanmay dnn

Farkl model snfnz varsa veya her snfn birok zellii varsa, tm ayrtrma kodunu elle yazmak zaman alc ve hataya ak hale gelir.

Bu gibi durumlarda kod oluturma(code generation) ok daha iyi bir seenektir.

resource


Original Link: https://dev.to/gulsenkeskin/dartflutter-da-json-ayristirma-104b

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To