How to decrypt a json response with gzip encoded data in flutter? - json

The Json response has encrypted objects which has to be decrypted to get the actual process. In android GZip was used .How can I achieve this The sample Json is as mentioned below.Any help is really appreciated.
{
"Data": "1.´ABCD´1150275,11028´01-Jan-2021´8,000.00´",
"Data": [
{
"Element": "8iMAAB+LCAAAAAAABADt1T8zBxwHgkefKcGh98Zcdz8FSqj9DMzK4d+L0Nj1tveNR2w6M8rRs3PJWBFDy"
},
{
"Element": "B1AV4bGp6JzQJI8ChnxzixrlT8vKnYHPwRM8zykKVn2gkceAFdxMwU0to"
}
],
"Status": 1,
"Msg": "Success",
"APIVersion": "1.4"
}
Basically how to decrypt a Gzip string. The same process was done in android ,but im new to flutter
Android java code is attached. i want to achieve something like that in flutter
public static String decompress(String zipText) throws IOException {
byte[] compressed = Base64.decode(zipText, Base64.DEFAULT);
if (compressed.length > 4) {
GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressed, 4,compressed.length - 4));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int value = 0; value != -1; ) {
value = gzipInputStream.read();
if (value != -1) {
baos.write(value);
}
}
gzipInputStream.close();
baos.close();
return new String(baos.toByteArray(), StandardCharsets.UTF_8);
} else {
return "";
}
}
On way i tried was
List<int> data = utf8.encode(zipText);
var deCompressedString = GZipDecoder().decodeBytes(data);
print(deCompressedString);
Which throw exception
Unhandled Exception: FormatException: Invalid GZip Signature

For decrypt zipped: How to decode a Gzip Http Response in Flutter?
EDIT
decompress like this
String decompress(String zipText) {
final List<int> compressed = base64Decode(zipText);
if (compressed.length > 4) {
Uint8List uint8list = GZipDecoder().decodeBytes(compressed.sublist(4, compressed.length - 4));
// print( String.fromCharCodes(uint8list));
return String.fromCharCodes(uint8list);
} else {
return "";
}
}

Related

Esp 8266 parse json async

I'm using asyncHTTPrequest for async request to a REST API in ESP8266.
I receive the response in JSON format but can't parse it.
This kind of parsing was working while i used to made sync call to API.
I tried to store the request->responseText() into a String variable because its return a String, but the variable never get any value.
void sendRequest() {
if (request.readyState() == 0 || request.readyState() == 4) {
request.open("GET", "http://192.168.1.103:45456/api/systems/1013/arduino");
request.send();
}
}
void requestCB(void* optParm, asyncHTTPrequest* request, int readyState) {
if (readyState == 4) {
Serial.println(request->responseText());
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(2) + JSON_OBJECT_SIZE(2) + 2*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8)+816;
DynamicJsonBuffer jsonBuffer(capacity);
JsonObject& root = jsonBuffer.parseObject(request->responseText());
String a = request->responseText();
Serial.println(a);
JsonObject& schState = root["dataForArduino"][0];
String beginTime = schState["start"]; // "2019-12-02T21:51:00"
}
}
void setup() {
Serial.begin(9600);
wifi.Connect();
request.onReadyStateChange(requestCB);
ticker.attach(5, sendRequest);
}
I have wrote json parsing function (__get_from_json) to get key value from json here
e.g. if you have json response like
{
"timestamp" : "2020-04-01 19:20:49"
}
and in your application you want to parse timestamp value from it then
char response[max_response_size] = "{ \"timestamp\" : \"2020-04-01 19:20:49\" }";
char key[max_key_size] = "timestamp";
char value[max_value_size] = "";
if( __get_from_json( response, key, value, max_value_size ) ){
Serial.println(value);
}
I had the same problem and added .c_str() to get the response to print.
So in your example it would be:
String a = request->responseText();
Serial.println(a.c_str());
For the JSON I also needed to add .c_str()
DynamicJsonDocument jsonDoc(2048);
DeserializeJson(jsonDoc, a.c_str());

Flutter json decode returns null

I'm getting a null return when I run the following code. Apparently I'm not accessing json correctly.
Is there another way to access json data? Or is it ok to use it like that?
Future Class - parsing json from a url
Future<List<User>> _getUsers() async {
var data = await http.get("https://...api.php");
if (data.statusCode == 200) {
print('Status Code 200: Ok!');
var jsonData = json.decode(data.body);
List<User> users = [];
for (var u in jsonData[0]) {
print(u[0]["title"]);
User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"]);
users.add(user);
}
print(users.length);
return users;
} else {
throw Exception('Failed to load json');
}
}
Class
class User {
final int id;
final String source;
final String desc;
final String link;
final String title;
User(this.id, this.source, this.desc, this.link, this.title);
}
Basic json structure:
{
"0":{
"id":0,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
},
"1":{
"id":1,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
}
}
What am missing here? thanks.
You're trying to use something that isn't a list as a list. The json structure you've provided looks like part of an object and not a list.
A list would look like this:
[{
"id": 0,
"source": "XXX",
"link": "XXXX",
"title": "XXXX",
"desc": "XXXX"
}]
But since the underlying structure is a Map you could iterate over the keys, doing something like this:
for (var k in jsonData.keys) {
var u = jsonData[k];
print(u["title"]);
User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"]);
}
Your json structure is not a real json. But if your json is like this:
{
"0":{
"id":0,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
},
"1":{
"id":1,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
}
}
You can get data like this:
for (int i = 0; i < length; i ++) {
User user = User(u["$i"]["id"], u["$i"]["source"], u["$i"]["desc"], u["$i"]["link"], u["$i"]["title"]);
users.add(user);
}

Flutter - error no such file or directory when reading JSON file

Hi so I am trying to convert JSON to objects but when I read the file it throws up an exception:
FileSystemException: Cannot open file, path = 'D:/AndroidStudio/my_app/assets/data/questions.json' (OS Error: No such file or directory, errno = 2)
here is the code:
String loadQuestionAsset() {
String jsonString;
new File('D:/AndroidStudio/my_app/assets/data/questions.json').readAsString().then((String contents) {
jsonString = contents;
});
return jsonString;
}
List<Question> parseJsonForQuestion() {
Map decoded = jsonDecode(loadQuestionAsset());
List<Question> questions = new List<Question>();
for (var question in decoded['questions']) {
questions.add(new Question(question['question'], question['bool']));
}
return questions;
}
and the JSON file:
{
"questions": [
{
"question": "Elon Musk is human",
"bool": false
},
{
"question": "Pizza is healthy",
"bool": false
},
{
"question": "Flutter is awesome",
"bool": true
}
]
}
Thanks for help :)
Path you need to provide is: assets/data/questions.json.
Now, in order to read it, you have to add this also into assets in pubspec.yaml file.
flutter:
assets:
- data/questions.json
Then, in order to read, you should use rootBundle:
Map map = await rootBundle
.loadStructuredData('assets/data/questions.json', (String s) async {
return json.decode(s);
});
I hope it works :)
You can do:
String loadQuestionAsset() {
String jsonString;
File('D:/AndroidStudio/my_app/assets/data/questions.json').create().readAsString().then(String contents) {
jsonString = contents;
});
return jsonString;
}

Parsing json in apex

Hello I have created a RESTful web services which returns the responce in below format :
[
{"empId":1,"empName":"A"},
{"empId":2,"empName":"B"},
{"empId":3,"empName":"C"},
{"empId":4,"empName":"D"},
{"empId":5,"empName":"E"}
]
I have written the simple visualforce page to call the method named 'lookup' on button click action. My Apex class is given below.
public class REST {
public PageReference lookup()
{
string resp;
// Note this version of the API is only for the US
string endpoint ='http://localhost:8080/RESTfulExample/rest/json/metallica/get';
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setMethod('GET');
req.setEndpoint(endpoint);
try {
res = http.send(req);
} catch (Exception e) {
system.debug(LoggingLevel.Error, 'Error HTTP response code = '+res.getStatusCode()+'; calling '+endpoint );
return null;
}
resp = res.getBody();
JSONParser parser = JSON.createParser(resp);
// Parsing The JSON & set the list of values to the variables 'empid' & 'empname'
return null;
}
}
Can anyone help me how I can use JSON parser to parse the JSON and to store the values to the variables.
Thank You !!!
If you would like to use JSONParser here is an example from the Salesforce documentation on JSONParser(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_json_jsonparser.htm):
public class JSONParserUtil {
#future(callout=true)
public static void parseJSONResponse() {
Http httpProtocol = new Http();
// Create HTTP request to send.
HttpRequest request = new HttpRequest();
// Set the endpoint URL.
String endpoint = 'https://docsample.herokuapp.com/jsonSample';
request.setEndPoint(endpoint);
// Set the HTTP verb to GET.
request.setMethod('GET');
// Send the HTTP request and get the response.
// The response is in JSON format.
HttpResponse response = httpProtocol.send(request);
System.debug(response.getBody());
/* The JSON response returned is the following:
String s = '{"invoiceList":[' +
'{"totalPrice":5.5,"statementDate":"2011-10-04T16:58:54.858Z","lineItems":[' +
'{"UnitPrice":1.0,"Quantity":5.0,"ProductName":"Pencil"},' +
'{"UnitPrice":0.5,"Quantity":1.0,"ProductName":"Eraser"}],' +
'"invoiceNumber":1},' +
'{"totalPrice":11.5,"statementDate":"2011-10-04T16:58:54.858Z","lineItems":[' +
'{"UnitPrice":6.0,"Quantity":1.0,"ProductName":"Notebook"},' +
'{"UnitPrice":2.5,"Quantity":1.0,"ProductName":"Ruler"},' +
'{"UnitPrice":1.5,"Quantity":2.0,"ProductName":"Pen"}],"invoiceNumber":2}' +
']}';
*/
// Parse JSON response to get all the totalPrice field values.
JSONParser parser = JSON.createParser(response.getBody());
Double grandTotal = 0.0;
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'totalPrice')) {
// Get the value.
parser.nextToken();
// Compute the grand total price for all invoices.
grandTotal += parser.getDoubleValue();
}
}
system.debug('Grand total=' + grandTotal);
}
}
Although from what you say in your question I think it would be simpler to do JSON Deserialization.
Here is an example on how to do it:
Wrapper Class
public class EmployeeWrapper {
public Integer empId {get;set;}
public String empName {get;set;}
}
JSON Deserialization
String jsonContent = '[{"empId": 1,"empName": "A"}, {"empId": 2,"empName": "B"}, {"empId": 3,"empName": "C"}, {"empId": 4,"empName": "D"}, {"empId": 5,"empName": "E"}]';
List<EmployeeWrapper> employeeWrapperList = (List<EmployeeWrapper>)JSON.deserialize(jsonContent, List<EmployeeWrapper>.class);
System.debug(employeeWrapperList);
//Do actions to WrapperList

CodeFluent JSON Serialization Does Not Work for All Fields

I'm using CodeFluent JsonUtilities to convert an object to JSON. Using anything else seems to have various other issues (e.g. Circular Referencing).
Here's some functions I use to convert to JSON for ASP.NET MVC, using CodeFluent.Runtime.Utilities namespace (for the JsonUtilities).
public static ContentResult ConvertToJsonResponse(object obj)
{
string json = JsonUtilities.Serialize(obj);
return PrepareJson(json);
}
/// <summary>
/// Converts JSON string to a ContentResult object suitable as a response back to the client
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static ContentResult PrepareJson(string json)
{
ContentResult content = new ContentResult();
content.Content = json;
content.ContentType = "application/json";
return content;
}
The problem is when I use JsonUtilities to convert an object it seems to have skipped some nested objects.
For example, I tried to convert DataSourceResult object (from Telerik) to JSON using CodeFluent.
public ActionResult UpdateTeam([DataSourceRequest]DataSourceRequest request, TeamViewModel teamViewModel)
{
ModelState.AddModelError("", "An Error!");
DataSourceResult dataSourceResult = new[] { teamViewModel }.ToDataSourceResult(request, ModelState);
ContentResult ret = CodeFluentJson.ConvertToJsonResponse(dataSourceResult);
return ret;
}
The dataSourceResult holds three main properties:
Data - which hold my Model that contains my data.
Total - which holds the amount of data objects there are.
Errors - which holds all the errors of my MVC model. It is very nested, with a lot of properties under it.
When I try to use CodeFluent utilities to convert the DataSourceResult object it works to convert "Data", and "Total" fields, but with Errors, it skips it entirely, resulting in the below JSON string:
{
"Data":[
{
"ExampleProperty":"ExampleValue"
}
],
"Total":1,
"AggregateResults":null,
"Errors":{ }
}
I'm guessing the issue is with the "Errors" object being too nested for the CodeFluent converter.
So my question is are there any CodeFluent serialization options/code I'm missing to work with heavily nested objects for JSON conversion?
The problem comes from the fact you're creating a model error with an empty key. It's not forbidden but JsonUtilities just skip dictionary values with an empty key, by design.
Just use a real key, like this:
ModelState.AddModelError("my first error", "An Error!");
ModelState.AddModelError("my second error", "An Error!");
And you'll see the errors collection serialized, like this:
{
"Data":[
{
"ExampleProperty":"ExampleValue"
}],
"Total": 1,
"AggregateResults": null,
"Errors": {
"my first error": {
"errors": [
"An Error!"
]
},
"my second error": {
"errors": [
"An Error!"
]
}
}
}
Otherwise, if you really want to keep empty keys, then you can leverage the JsonUtilitiesOptions class that has callbacks for tweaking the serialization (and deserialization) process. Careful with this as you can easily break JSON syntax. This is how you could do it, in a way that should handle all cases:
JsonUtilitiesOptions options = new JsonUtilitiesOptions();
options.WriteValueCallback += (e) =>
{
IDictionary valueDic = e.Value as IDictionary;
if (valueDic != null)
{
e.Writer.Write('{');
bool first = true;
foreach (DictionaryEntry entry in valueDic)
{
if (!first)
{
e.Writer.Write(',');
}
else
{
first = false;
}
// reuse JsonUtilities already written functions
JsonUtilities.WriteString(e.Writer, entry.Key.ToString(), e.Options);
e.Writer.Write(':');
// object graph is for cyclic/infinite serialization checks
JsonUtilities.WriteValue(e.Writer, entry.Value, e.ObjectGraph, e.Options);
}
e.Writer.Write('}');
e.Handled = true; // ok, we did it
}
};
string json = JsonUtilities.Serialize(obj, options);
Now, you'll get this result:
{
"Data":[
{
"ExampleProperty":"ExampleValue"
}],
"Total": 1,
"AggregateResults": null,
"Errors": {
"": {
"errors": [
"An Error!"
]
}
}
}