From ef9cc8e3ccb240380489618254013787ea6d5cf4 Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Fri, 28 Oct 2022 20:23:05 +0530 Subject: [PATCH 1/6] Added: parser for response (partially works) Need to handle array of dynamic items, and instead of converting string to uppercase, needs to convert from snake_case --- lib/vaahextendflutter/services/api.dart | 44 +++++++++++++++++++++---- lib/view/pages/home.dart | 17 +++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index fce477ca..101208fc 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -31,6 +31,28 @@ class Api { return Options(headers: header, contentType: contentType); } + static dynamic parseResponse(dynamic data) { + if (data is List) { + List> parsedData = []; + for (var e in data) { + parsedData.add(parseResponse(e)); + } + return parsedData; + } else if (data is Map) { + Map parsedData = {}; + data.forEach( + (key, value) { + dynamic parsedvalue = parseResponse(value); + parsedData.addAll({ + key.toUpperCase(): parsedvalue, + }); + }, + ); + return parsedData; + } + return data; + } + // return type of ajax is ApiResponseType? so if there is error // then null will be returned otherwise ApiResponseType object static Future ajax({ @@ -80,7 +102,12 @@ class Api { } if (callback != null) { - await callback(responseData, response); + dynamic newdata = parseResponse({ + 'property_a': 'Data_a', + 'property_b': [{'Data_Key_b': 'Data_b'}], + 'property_c': {'Data_Key_c': 'Data_c'} + }); + await callback(newdata, response); } return; @@ -259,7 +286,10 @@ class Api { await Helpers.showErrorToast(content: 'Invalid request type!'); break; } - _showToast(content: 'ERR: Invalid request type!', color: AppTheme.colors['danger']!,); + _showToast( + content: 'ERR: Invalid request type!', + color: AppTheme.colors['danger']!, + ); break; } } @@ -457,7 +487,8 @@ class Api { // ignore: unnecessary_null_comparison if (Helpers.showErrorToast != null) { await Helpers.showErrorToast( - content: errors.isEmpty ? 'Error' : 'ERR: ${errors.join('\n')}', + content: + errors.isEmpty ? 'Error' : 'ERR: ${errors.join('\n')}', ); return; } @@ -484,7 +515,9 @@ class Api { toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, backgroundColor: color.withOpacity(0.5), - textColor: color == AppTheme.colors['white'] ? AppTheme.colors['black'] : AppTheme.colors['whiteColor'], + textColor: color == AppTheme.colors['white'] + ? AppTheme.colors['black'] + : AppTheme.colors['whiteColor'], fontSize: 16.0, ); } @@ -505,8 +538,7 @@ class Api { children: [ if (content != null && content.isNotEmpty) Text(content.join('\n')), - if (content != null && content.isNotEmpty) - verticalMargin12, + if (content != null && content.isNotEmpty) verticalMargin12, if (hint != null && hint.trim().isNotEmpty) Text(hint), ], ), diff --git a/lib/view/pages/home.dart b/lib/view/pages/home.dart index 9b10f85c..eb76e97e 100644 --- a/lib/view/pages/home.dart +++ b/lib/view/pages/home.dart @@ -1,7 +1,8 @@ - import 'package:flutter/material.dart'; import '../../vaahextendflutter/base/base_stateful.dart'; +import '../../vaahextendflutter/helpers/console.dart'; +import '../../vaahextendflutter/services/api.dart'; class TeamHomePage extends StatefulWidget { static Route route() { @@ -18,7 +19,6 @@ class TeamHomePage extends StatefulWidget { } class _TeamHomePageState extends BaseStateful { - @override void afterFirstBuild(BuildContext context) { super.afterFirstBuild(context); @@ -29,9 +29,18 @@ class _TeamHomePageState extends BaseStateful { super.build(context); return Scaffold( appBar: AppBar(), - body: const Center( - child: Text('Team App Home Page'), + body: Center( + child: ElevatedButton( + onPressed: () async => + await Api.ajax(url: '/api/data', callback: callback), + child: const Text('Parse Response'), + ), ), ); } } + +Future callback(dynamic data, dynamic res) async { + Console.info(data.toString()); +} + From 607bd26986ac03eae572b468d36af82ddfc2edda Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Mon, 31 Oct 2022 13:09:59 +0530 Subject: [PATCH 2/6] added: snake_case to camelCase parsing of response all data types are supported: list, map, bool, string, List containing map, map containing list, list containing lists, map containing maps. --- lib/vaahextendflutter/services/api.dart | 22 ++++++++++++++-------- lib/view/pages/home.dart | 20 ++------------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index 101208fc..06f28ceb 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -33,7 +33,7 @@ class Api { static dynamic parseResponse(dynamic data) { if (data is List) { - List> parsedData = []; + dynamic parsedData = []; for (var e in data) { parsedData.add(parseResponse(e)); } @@ -44,7 +44,7 @@ class Api { (key, value) { dynamic parsedvalue = parseResponse(value); parsedData.addAll({ - key.toUpperCase(): parsedvalue, + _snakeCasetoLowerCamelCase(key): parsedvalue, }); }, ); @@ -53,6 +53,16 @@ class Api { return data; } + static String _snakeCasetoLowerCamelCase(String data) { + List sentence = data.split('_'); + String result = ''; + for (var e in sentence) { + result += e[0].toUpperCase()+e.substring(1); + } + return result[0].toLowerCase()+result.substring(1); + } + + // return type of ajax is ApiResponseType? so if there is error // then null will be returned otherwise ApiResponseType object static Future ajax({ @@ -102,12 +112,7 @@ class Api { } if (callback != null) { - dynamic newdata = parseResponse({ - 'property_a': 'Data_a', - 'property_b': [{'Data_Key_b': 'Data_b'}], - 'property_c': {'Data_Key_c': 'Data_c'} - }); - await callback(newdata, response); + await callback(parseResponse(responseData), response); } return; @@ -559,3 +564,4 @@ class Api { ); } } + diff --git a/lib/view/pages/home.dart b/lib/view/pages/home.dart index eb76e97e..82885356 100644 --- a/lib/view/pages/home.dart +++ b/lib/view/pages/home.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import '../../vaahextendflutter/base/base_stateful.dart'; -import '../../vaahextendflutter/helpers/console.dart'; -import '../../vaahextendflutter/services/api.dart'; class TeamHomePage extends StatefulWidget { static Route route() { @@ -19,28 +17,14 @@ class TeamHomePage extends StatefulWidget { } class _TeamHomePageState extends BaseStateful { - @override - void afterFirstBuild(BuildContext context) { - super.afterFirstBuild(context); - } - @override Widget build(BuildContext context) { super.build(context); return Scaffold( appBar: AppBar(), - body: Center( - child: ElevatedButton( - onPressed: () async => - await Api.ajax(url: '/api/data', callback: callback), - child: const Text('Parse Response'), - ), + body: const Center( + child: Text('Team App Home Page'), ), ); } } - -Future callback(dynamic data, dynamic res) async { - Console.info(data.toString()); -} - From c7aad15f3528fcea580ada02d181d968eeaa9f14 Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Tue, 1 Nov 2022 12:09:13 +0530 Subject: [PATCH 3/6] Added: camelCase to snake_case parsing --- lib/vaahextendflutter/services/api.dart | 55 +++++++++++++++++++------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index 06f28ceb..6e782506 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -31,20 +31,23 @@ class Api { return Options(headers: header, contentType: contentType); } - static dynamic parseResponse(dynamic data) { + static dynamic _parseKeys({ + required dynamic data, + required Function changeKeys, + }) { if (data is List) { dynamic parsedData = []; for (var e in data) { - parsedData.add(parseResponse(e)); + parsedData.add(_parseKeys(data: e, changeKeys: changeKeys)); } return parsedData; } else if (data is Map) { Map parsedData = {}; data.forEach( (key, value) { - dynamic parsedvalue = parseResponse(value); + dynamic parsedvalue = _parseKeys(data: value, changeKeys: changeKeys); parsedData.addAll({ - _snakeCasetoLowerCamelCase(key): parsedvalue, + changeKeys(key): parsedvalue, }); }, ); @@ -53,16 +56,21 @@ class Api { return data; } + static String _lowerCamelCaseToSnakeCase(String data) { + List parts = data.split(RegExp(r"(?=(?!^)[A-Z])")); + String result = parts.join('_'); + return result.toLowerCase(); + } + static String _snakeCasetoLowerCamelCase(String data) { List sentence = data.split('_'); String result = ''; for (var e in sentence) { - result += e[0].toUpperCase()+e.substring(1); + result += e[0].toUpperCase() + e.substring(1); } - return result[0].toLowerCase()+result.substring(1); + return result[0].toLowerCase() + result.substring(1); } - // return type of ajax is ApiResponseType? so if there is error // then null will be returned otherwise ApiResponseType object static Future ajax({ @@ -112,7 +120,13 @@ class Api { } if (callback != null) { - await callback(parseResponse(responseData), response); + await callback( + _parseKeys( + data: responseData, + changeKeys: _snakeCasetoLowerCamelCase, + ), + response, + ); } return; @@ -231,9 +245,16 @@ class Api { break; case 'post': + Console.info(_parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ).toString()); response = await _dio.post( '$_apiBaseUrl$url', - data: params, + data: _parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ), queryParameters: query, options: options, ); @@ -242,7 +263,10 @@ class Api { case 'put': response = await _dio.put( '$_apiBaseUrl$url', - data: params, + data: _parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ), queryParameters: query, options: options, ); @@ -251,7 +275,10 @@ class Api { case 'patch': response = await _dio.patch( '$_apiBaseUrl$url', - data: params, + data: _parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ), queryParameters: query, options: options, ); @@ -260,7 +287,10 @@ class Api { case 'delete': response = await _dio.delete( '$_apiBaseUrl$url', - data: params, + data: _parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ), queryParameters: query, options: options, ); @@ -564,4 +594,3 @@ class Api { ); } } - From 957a70587322463928aec780327b77cef060654b Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Wed, 2 Nov 2022 20:17:24 +0530 Subject: [PATCH 4/6] Fixed: _snakeCasetoLowerCamelCase parsing --- lib/vaahextendflutter/services/api.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index 6e782506..e5c0c000 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -64,11 +64,18 @@ class Api { static String _snakeCasetoLowerCamelCase(String data) { List sentence = data.split('_'); + sentence.removeWhere((element) => element.isEmpty); String result = ''; for (var e in sentence) { result += e[0].toUpperCase() + e.substring(1); } - return result[0].toLowerCase() + result.substring(1); + if(result.isEmpty){ + return data; + } + if (result[0].isAlphabetOnly){ + result = result[0].toLowerCase() + result.substring(1); + } + return result; } // return type of ajax is ApiResponseType? so if there is error From 47de24684e63c817aae1ef2008678413f7edb054 Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Thu, 3 Nov 2022 12:13:34 +0530 Subject: [PATCH 5/6] Removed: unnecessary console log --- lib/vaahextendflutter/services/api.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index e5c0c000..289c77be 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -252,10 +252,6 @@ class Api { break; case 'post': - Console.info(_parseKeys( - data: params, - changeKeys: _lowerCamelCaseToSnakeCase, - ).toString()); response = await _dio.post( '$_apiBaseUrl$url', data: _parseKeys( From 1d56d815a357fbfe3e33d6d8c846cf0faab6f0b6 Mon Sep 17 00:00:00 2001 From: Prajapati Chintan Date: Thu, 3 Nov 2022 12:51:43 +0530 Subject: [PATCH 6/6] Added: jsonEncoding for request data, and parsing occurs in one place --- lib/vaahextendflutter/services/api.dart | 31 +++++++++++-------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/lib/vaahextendflutter/services/api.dart b/lib/vaahextendflutter/services/api.dart index 289c77be..50b99e21 100644 --- a/lib/vaahextendflutter/services/api.dart +++ b/lib/vaahextendflutter/services/api.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; @@ -69,10 +70,10 @@ class Api { for (var e in sentence) { result += e[0].toUpperCase() + e.substring(1); } - if(result.isEmpty){ + if (result.isEmpty) { return data; } - if (result[0].isAlphabetOnly){ + if (result[0].isAlphabetOnly) { result = result[0].toLowerCase() + result.substring(1); } return result; @@ -242,6 +243,12 @@ class Api { options.headers = customHeader; } } + String encodedData = jsonEncode( + _parseKeys( + data: params, + changeKeys: _lowerCamelCaseToSnakeCase, + ), + ); switch (method) { case 'get': response = await _dio.get( @@ -254,10 +261,7 @@ class Api { case 'post': response = await _dio.post( '$_apiBaseUrl$url', - data: _parseKeys( - data: params, - changeKeys: _lowerCamelCaseToSnakeCase, - ), + data: encodedData, queryParameters: query, options: options, ); @@ -266,10 +270,7 @@ class Api { case 'put': response = await _dio.put( '$_apiBaseUrl$url', - data: _parseKeys( - data: params, - changeKeys: _lowerCamelCaseToSnakeCase, - ), + data: encodedData, queryParameters: query, options: options, ); @@ -278,10 +279,7 @@ class Api { case 'patch': response = await _dio.patch( '$_apiBaseUrl$url', - data: _parseKeys( - data: params, - changeKeys: _lowerCamelCaseToSnakeCase, - ), + data: encodedData, queryParameters: query, options: options, ); @@ -290,10 +288,7 @@ class Api { case 'delete': response = await _dio.delete( '$_apiBaseUrl$url', - data: _parseKeys( - data: params, - changeKeys: _lowerCamelCaseToSnakeCase, - ), + data: encodedData, queryParameters: query, options: options, );