How to Read JSON file in Dart console app? - json

This is a full-console app in dart. Its not flutter.
I need to import data from a local json file and send it as response. I need to read the data as array of Map in dart. The data is in following format.
{
"users":[
{
"id":1,
"user":"user1",
"password":"p455w0rd"
},
{
"id":2,
"user":"user2",
"pass":"p455w0rd"
}
]
}
Every where I see the Flutter example which imports flutter/services as rootBundle to read into the JSON file. I do not find a way to implement this in pure dart.

Use dart:io and dart:convert.
Simple example below. Remember to add exception handling if the file does not exist or has wrong format.
import 'dart:convert';
import 'dart:io';
Future<List<Map>> readJsonFile(String filePath) async {
var input = await File(filePath).readAsString();
var map = jsonDecode(input);
return map['users'];
}

Below is the sample code which you can use to synchronously read a text/json file as a string, displays its content and creates corresponding objects. This will work without using any flutter classes.
For reading JSON/txt file,user 'dart:io' package.
Once the file has been read as a string, use JsonDecoder class to convert the json into corresponding data model objects
import 'dart:io';
import 'dart:convert';
const String FILEPATH = "C:\\test\\dartlang\\users.json";
const JsonDecoder decoder = JsonDecoder();
class USER {
int? id;
String? user;
String? password;
//{ } - implies named arguments
USER({this.id, this.user, this.password});
#override
String toString() {
return "{id:$id,user:$user,password:$password}";
}
}
void main() {
List<USER>? eMP;
//synchronously read file contents
var jsonString = File(FILEPATH).readAsStringSync();
//print(jsonString);
//pass the read string to JsonDecoder class to convert into corresponding Objects
final Map<String, dynamic> jsonmap = decoder.convert(jsonString);
//DataModel - key = "users", value = "ARRAY of Objects"
var value = jsonmap["users"];
if (value != null) {
eMP = <USER>[];
//Each item in value is of type::: _InternalLinkedHashMap<String, dynamic>
value.forEach((item) => eMP?.add(new USER(id:item["id"],user:item["user"],password:item["password"] )));
}
eMP?.forEach((element) => print(element));
}
Save the following json file in your filepath.
{
"users":[{"id":1,"user":"user1", "password":"p455w0rd"},
{"id":2,"user":"user2","password":"p455w0rd"}
]
}

First import dart:convert.
You can parse data from a JSON file as follows:
Future<void> readJson() async {
final String response = await rootBundle.loadString('assets/sample.json');
final data = await json.decode(response);
final users = data['users'];
// ...
}

Related

How to send list of model objects in json format to API in flutter

I am working on a Food Delivery App in Flutter and I have a list of model objects in my cart System. I need to send this list to API in JSON format so I convert that to JSON before sending it to server but i am getting error:
errors: {: [Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Metronic.Models.FoodOrderInsert' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
I am beginner in Flutter and your kind response will highly be appreciated.
I am currently converting list and sending it to API like this:
I have my List of modelbjects:
List<FoodDetail> foodOrderDetails = [...]
var jsonObjectsList = [];
//Here I convert my list of FoodDetails into list of jsonObjects
for (var item in foodOrderDetail) {
jsonObjectsList.add(item.toJson());
}
await http
.post(
Uri.parse(url),
headers: ApiURLs.header,
body: jsonEncode(jsonObjectsList)
)
And my API required data is:
[{
"OrderId": 0,
"ProductId": 0,
"Quantity": 0,
"Price": 0}]
my FoodDetail class contain same these properties and converted to json but the problem I think is in conveting whole list to json.
i suggestion to use DIO lib its automatically convert your data to json
check it: https://pub.dev/packages/dio
use this class to parse the server response
FoodExample foodExample=FoodExample.fromJson(jsonEncode(jsonObjectsList))
with this line you will have access to all the attributes of the class
class FoodExample {
int orderId;
int productId;
int quantity;
int price;
FoodExample({this.orderId, this.productId, this.quantity, this.price});
FoodExample.fromJson(Map<String, dynamic> json) {
if(json["OrderId"] is int)
this.orderId = json["OrderId"];
if(json["ProductId"] is int)
this.productId = json["ProductId"];
if(json["Quantity"] is int)
this.quantity = json["Quantity"];
if(json["Price"] is int)
this.price = json["Price"];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data["OrderId"] = this.orderId;
data["ProductId"] = this.productId;
data["Quantity"] = this.quantity;
data["Price"] = this.price;
return data;
}
}
I solved my question by using Dio package,
That was the error due to http package internal code.
My Method for posting list to Server:
Future<int> insertFoodOrderDetails(List<FoodOrderDetail> foodOrderDetail) async {
var dio = Dio();
var mapData;
var url = ApiURLs.baseUrl + ApiURLs.insertFoodOrderDetails;
var jsonObjectsList = [];
for (var item in foodOrderDetail) {
jsonObjectsList.add(item.toMap());
}
await
dio.post(
url,
queryParameters: ApiURLs.header,
data: jsonObjectsList
)
.then((value) {
mapData = value.data as Map<String, dynamic>;
});
if (mapData['Status'] == 'Inserted Successfully') {
print(mapData['Id']);
return mapData['Id'] ;
}
else{
return 0;
}
}

Display the complete json data from API response in flutter

I'm getting the json data from the API call but its not displaying the complete data.There are a lot of properties to work with and creating the model would be difficult as it's my first time working on any API.So i wanted to use app.quicktype.io to parse the json data directly into dart code for which i need to get the complete json data.Right now only little bit of the json data is being displayed in the console.
CODE:
Future<void> getContacts() async {
var client = http.Client();
String contacts_url =
'https://mylinkexample.com';
String basicAuth =
'Basic mykeyexampele';
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
var jsonString = jsonDecode(response.body);
print(response.statusCode);
print(jsonString);
}
Use this :
import 'dart:developer' as developer;
test() {
developer.log(response.body);
}

How to deserialize a string to a object and then set as a generic in flutter

So I have this api call that have a response in the form of: boolean:successful, int:responseCode, String:reponse and T:Data. The Data is a generic, I could be string, int, DataModel etc. My issue is I can not conver the Json or String from of Data to an object as the type is generic. I try to have the deseralization for a data model called event resource. and it works if I do EventResource.fromJson(json['Data']) but I can not set that to Data. I have looked on stack overflow and found this one post similar to mine here. But when I try to implement the answer it fails stating that it can not find the constructor _fromJson even though I had one.
This is how I call fromJson:
ResponseModel responseModel = ResponseModel.fromJson(json.decode(response.body));
My Class (ResponseModel):
import 'EventResource.dart';
import 'dart:convert' show json;
class ResponseModel<T> {
var successful;
int responseCode;
String response;
T Data;
ResponseModel.fromJson(Map<String, dynamic> json){
successful = json['successful'];
responseCode = json['responseCode'];
response = json['response'];
Data = Data is EventResource? EventResource.fromJson(json['Data']) :json['Data']; // this is what I want but cant get to work
}
Map<String, dynamic> toJson() {
return {
'successful': successful,
'responseCode': responseCode,
'response': response,
'Data': Data,
};
}
}
So after sending some time on this I realized rather than have Data be a generic it could be assigned the type var and it would take in any data and we could easily cast it with out having the issues of casting generics etc.
class ResponseModel {
var successful;
int responseCode;
String response;
var Data;
ResponseModel.fromJson(Map<String, dynamic> json){
successful = json['successful'];
responseCode = json['responseCode'];
response = json['response'];
Data = Data is EventResource? EventResource.fromJson(json['Data']) :json['Data'];
}
Map<String, dynamic> toJson() {
return {
'successful': successful,
'responseCode': responseCode,
'response': response,
'Data': Data,
};
}
}

Decoding json from google firebase rest api using Dart, not Flutter

I can retrieve a list of documents from a collection in a Cloud Firestore instance, in Firebase. The response contains the most verbose json I have ever seen. Here is a taste, ...
{
documents: [
{
name: projects/myprojectId/databases/(default)/documents/mycollection/0HC2spBFxEMNUc8VQLFg,
fields: {
name: {
stringValue: Jim's Bait Shop},
taxId: {
stringValue:
},
mailingAddress: {
mapValue: {
fields: {
streetAddress1: {
stringValue:
}
},
streetAddress2: {
stringValue:
},
state: {
stringValue: NC
},
city: {
stringValue: Boone
},
zipCode: {
stringValue:
}
}
}
}
},
createTime: 2020-08-31T19
:
54: 28.643464Z,
updateTime: 2020-09-01T02
:
35: 08.203028Z
},
{ ...
When trying to use jsonDecode, in dart:convert, it fails to de-serialize the json response into a collection of Dart objects.
'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
And if I use cUrl instead of Dart, the json response looks just as verbose.
I'm using the FirebaseClient in "package:firebase/firebase_io.dart" to authenticate and read the collection.
I tried to build a "reviver" function but jsonDecode would not accept it so I'm not sure how I messed that up.
Anyway, I'm not seeing much guidance in the documentation on how to marshal this verbose json response into Dart objects. I suspect this server-side Dart is somewhat new territory. I want to avoid packages that require Flutter because I'm using a prebuilt docker image, with the Dart runtime preinstalled, on Google Cloud Run. (Truthfully, I've already tried a few Flutter packages for Firestore and a Flutter docker image.) I'll take any suggestions you have.
Below is the file I've been using for testing.
import 'package:firebase/firebase_io.dart';
import 'credentials.dart'; // borrowed from a SO post
import 'dart:convert';
const base = 'https://firestore.googleapis.com/v1/projects/';
void main() async {
// get private key...
final credential = await Credentials.fetch(); // string
final fbClient = FirebaseClient(credential);
final path = base + 'my_project_id/databases/(default)/documents/my_collection'
'?mask.fieldPaths=name&mask.fieldPaths=taxId&mask.fieldPaths=mailingAddress&orderBy=orgId';
final response = await fbClient.get(path);
print(response);
final orgs = jsonDecode(response); // unhandled exception
fbClient.close();
}
I think I might need to switch to a more sophisticated json deserializer package, and annotate my model classes to explicitly map this gnarly json to specific Dart class properties. But I have not yet seen a Dart package that supports such capabilities.
I have tried to use "json_serializable: 3.4.1" but failed to get code generation to work.
An online json validator is saying the response is malformed due to an apostrophe but can I trust that? Doubt I can escape special chars.
The error message says that response is not a String, it's a Map.
That means that Firebase has already parsed the JSON for you and returns the parsed structure.
You don't need to use jsonDecode, just final orgs = response;.
The solution was to stop using FirebaseClient, because it was not wrapping the name-value pairs in double quotation marks. Just use normal http instead.
import 'package:http/http.dart' as http;
const base = 'https://firestore.googleapis.com/v1/projects/';
void main() async {
//
final uri = base + 'myproject/databases/(default)/documents/mycollection' +
'?mask.fieldPaths=name&mask.fieldPaths=taxId&mask.fieldPaths=mailingAddress&orderBy=orgId&alt=json';
var response = await http.get(uri);
// print(response.body);
var json = jsonDecode(response.body)['documents'] as List;
List l = json.map((o) => MyModelClass.fromJson(o)).toList();
https://pub.dev/packages/http

Trouble Parsing YouTube v3 JSON Response

I'm having a bit of trouble parsing the JSON response from YouTube but I need a bit of assistance doing so. I'm attempting to obtain the fields: id, videoId, thumbnails and url - using the following:
private String getUrl(String id) throws IOException, JSONException {
HttpClient client = new DefaultHttpClient();
HttpGet clientGetMethod = new HttpGet(YOUTUBE_INFO_URL.replace("_ID_", id));
HttpResponse clientResponse = null;
clientResponse = client.execute(clientGetMethod);
String infoString = _convertStreamToString(clientResponse.getEntity().getContent());
String urldata=new JSONObject(infoString).getJSONObject("id").getJSONObject("videoId").getJSONArray("thumbnails").getJSONObject(0).getString("url");
return new JSONObject(infoString).getJSONObject("id").getJSONObject("videoId").getJSONArray("thumbnails").getJSONObject(0).getString("url");
}
YouTube API v3 Response:
http://pastebin.com/LKWC2Cbz
However I continually get fatal errors due to incorrect parsing. Can someone spot where I may have gone wrong? I'm specifying the fields I need - however I feel like the structure must not match the JSON response in some manner.
So I assume that infoString contains the JSON response that you pasted to the pastebin link you shared.
This is my first Java program and I'm using Java 8 so things are a little bit different than in your code (I'm using JsonObject for example, not JSONObject, although when reading the program it should be clear what you need to modify)
package stackoverflowyoutubejson;
import java.io.IOException;
import javax.json.*;
public class StackOverflowYoutubeJson {
public static void main(String[] args) {
try {
JsonObject object;
// Instead of making a Http GET request I just read out the JSON file's contents saved down locally
try (JsonReader jsonReader = Json.createReader(StackOverflowYoutubeJson.class.getResourceAsStream("input/youtube-response.json"))) {
object = jsonReader.readObject();
}
// Obtaining the items array
JsonArray items = object.getJsonArray("items");
// Iterating the items array
for(int i = 0; i < items.size(); i++) {
JsonObject item = items.getJsonObject(i);
JsonString id = item.getJsonString("id");
System.out.println("id: " + id);
JsonObject snippet = item.getJsonObject("snippet");
JsonString videoId = snippet.getJsonObject("resourceId").getJsonString("videoId");
System.out.println("videoid: " + videoId);
JsonString url = snippet.getJsonObject("thumbnails").getJsonObject("default").getJsonString("url");
System.out.println("default thumbnail url: " + url);
System.out.println();
}
}
catch(IOException e) {
System.out.println(e);
}
}
}
The output of this program is:
id: "PL7ztmfZ6VHFYVLwdKgxI9lwOWFV_yoCFOK5o9K8KSE2s"
videoid: "PcfLDmkpzto"
default thumbnail url: "https://i.ytimg.com/vi/PcfLDmkpzto/default.jpg"
id: "PL7ztmfZ6VHFYVLwdKgxI9l7VIO-rUMLOT7pjiYSbTRPw"
videoid: "D9ohtWGSl9M"
default thumbnail url: "https://i.ytimg.com/vi/D9ohtWGSl9M/default.jpg"
id: "PL7ztmfZ6VHFYVLwdKgxI9l5gWA-vAfTbxQVrUWaMILLA"
videoid: "B1OluIUHLnY"
default thumbnail url: "https://i.ytimg.com/vi/B1OluIUHLnY/default.jpg"
id: "PL7ztmfZ6VHFYVLwdKgxI9l9A2H_-9HSzVlvT--kLf0TA"
videoid: "LjKpcUJSjtM"
default thumbnail url: "https://i.ytimg.com/vi/LjKpcUJSjtM/default.jpg"
id: "PL7ztmfZ6VHFYVLwdKgxI9l9nWIbKA-8Bnu3v_D6xEKaU"
videoid: "fTSmcQdLyhU"
default thumbnail url: "https://i.ytimg.com/vi/fTSmcQdLyhU/default.jpg"
So basically, if you have a JSON like this:
{
"field1": {
"nestedField1": "nestedValue1",
"nestedField2": "nestedValue2"
},
"field2": "value2"
}
You can access the fields like this:
JSONObject wholeJson = new JSONObject(jsonStringAsDescribedAbove);
JSONString field2 = wholeJson.getJSONString("field2"); // will contain value2
JSONObject field1 = wholeJson.getJSONObject("field1"); // will contain the whole field1 object
JSONString nestedField1 = wholeJson.getJSONObject("field1").getJSONString("nestedField1"); // or field1.getJSONString("nestedField1");, will contain nestedValue1
JSONString nestedField2 = wholeJson.getJSONObject("field1").getJSONString("nestedField2"); // or field1.getJSONString("nestedField2");, will contain nestedValue2