Table of Contents
In this article, we will see how to parse large JSON data with Isolates in Dart. We all know that everything is moving online right now, including business, services, and everything else. Additionally, they need to maintain their platform on both devices using an app or website in order to build those services, businesses, and educational institutions online. We will see how this can be done using JSON formatted data with Isolates in Dart based applications.
How to Parse Large JSON Data with Isolates in Dart
Also Read: Are Verification and Validation two different things in Flutter ?
Developers created the user interfaces and their backends so that things could be done online in accordance with the organization's requirements, security policies, and other policies that were discussed with the developers. Here, developers have two options - they can either mention their own tech stack to the company, which is why picking one is great, or, if the company has already chosen another tech stack, they can decide to use it.
The API data response, however, remains the same, or largely the same, regardless of the tech stack, domain, and other factors that can be chosen and compromised based on needs. In fact, as developers, we frequently send JSON-formatted data whenever a user requests any data from the backend. As such, it must always be handled along with the user interfaces, front end, and other backend tasks.
Why do we employ JSON
As a result, the backend API frequently returns responses in JSON format. It is primarily used for data exchange between servers and logical data modification in response to responses.
YAML, BSON, and other formats are some of the many alternatives to JSON. Nevertheless, JSON is the most widely used response format for sending data between servers in organizations. JSON has a variety of advantages over other response formats, some of which are listed below:-
- JSON describes the data it contains in both its syntax and internal implementation.
- JSON is closer to text. Since JSON is just text and not encoded like some other formats, it makes it very simple to manipulate the data to suit one's needs.
- JSON is about 2/3 the size of the response received in XML format, which makes it very small in comparison to other response formats like XML.
- JSON is simple to pick up, read, understand, and use from a front-end perspective.
Example
{ "data": [ { "name": "Rajesh", "email": "rajesh@gmail.com", "mob_no": "321654XXXX", "uId": 1 }, { "name": "Kamal", "email": "kamal@gmail.com", "mob_no": "357162XXXX", "uId": 2 }, { "name": "Raju", "email": "raju@gmail.com", "mob_no": "799597XXXX", "uId": 3 }, { "name": "Rajesh", "email": "rajesh@gmail.com", "mob_no": "788150XXXX", "uId": 4 }, ] }
Parsing Large JSON in Dart
Well, from the above points and explanation, we got to know that JSON is always/mostly beneficial from the perspective of reading, understanding, and applying it to real-life backend API responses. Yes, JSON is better when the payload is small, because it's easy to debug and understand the whole structure. But, when it comes to large systems, they always tend to have great response structures, which need to be parsed according to the usage and statistical benefits.
Now, in this section, we will mostly deal with the parsing of JSON in Dart. For parsing JSON in the dart, we mostly create a model, which is an exact copy of the data coming from the API.
class UserModel{ String name; String email; String mobNo; UserModel( { required this.name, required this.email, required this.mobNo } ); factory UserModel.fromJson(Map<String,dynamic> json){ return UserModel( name: json['name'], email:json['email'], mobNo:json['mob_no'] ); } }
Well, the above example is the model created for the JSON response that we created earlier in this article. In this model, we are mostly fetching the data from the resultant JSON into a class variable, which is named according to the same naming convention as the resultant API response.
Usage of Isolates in JSON Parsing
In the above code, we have seen how to parse JSON, from the resultant response of the API, but if the JSON payload is large, we need to parse it into a listing format, which can be done using Isolates.
import 'dart:convert'; class UserModelParser{ List<UserModel> _parseListOfJson(String encodeJson){ final json = jsonDecode(encodeJson); final result = json['data'] as List<dynamic>; return result.map((data)=>UserModel.fromJson(data)).toList(); } }
In the above code, we are passing the whole JSON received from the resultant API response, and then we are decoding the JSON. After decoding the JSON, we get the list of data, which is then mapped to “UserModel” and parsed individually. As we can see, “_parseListOfJson” is not an asynchronous method, so, it will take a lot of time to execute and give the result. So, parsing it in the background using the compute method will result in great results when compared with the above results.
import 'dart:convert'; import 'package:flutter/foundation.dart'; class UserModelParser{ Future<List<UserModel>> fetchInBackground(String encodeJson){ return compute(_parseListOfJson,encodeJson); } List<UserModel> _parseListOfJson(String encodeJson){ final json = jsonDecode(encodeJson); final result = json['data'] as List<dynamic>; return result.map((data)=>UserModel.fromJson(data)).toList(); } }
Similarly, we can also use Isolate.exit() for fast concurrency. Isolate.exit() can be used to take advantage of compute(), according to an update in Flutter v2.8.
class UserModelParser{ final String encodeJson; UserModelParser({required this.encodeJson}); Future<List<UserModel>> fetchInBackground(String encodeJson)async{ final port = ReceivePort(); await Isolate.spawn(_parseListOfJson,port.sendPort); return await port.first; } List<void> _parseListOfJson(SendPort port){ final json = jsonDecode(encodeJson); final result = json['data'] as List<dynamic>; final listOfResults = result.map((data)=>UserModel.fromJson(data)).toList(); Isolate.exit(port,listOfResults); } }
Isolates were primarily used in the code above to speed up concurrency and parse the resulting API response behind the scenes. We are obtaining the encoded JSON in this class. Later, the encodedJson is obtained using the function fetchInBackground(), which is then used to create a receivePort on its other end. An isolate that shares the same code as the current isolates is created and spawned by isolate. The encoded JSON is then accessed by _parseListofJson(), which parses each "UserModel" contained therein.
Applying JSON Parsing to the API Services
In the below code, we have called our API Service and applied parsing to the resultant API’s response.
class APIServices{ Future<List<UserModel>> downloadAndParseJson()async{ final response = await http.get(Uri.parse(GET_URL)); if(response.statusCode == 200){ final userModelParser = UserModelParser(); return userModelParser.fetchInBackground(response.body); } else{ throw Exception('Failed to fetch data from the API'); } } }
Conclusion
This article primarily focuses on debugging JSON, and it serves as an example of how to parse JSON data in large systems' resultant response APIs while using isolates. This article should have helped you understand JSON and how to use it from a dart and flutter perspective.