Parsing a JSON to convert some parameters into HEX/String - arrays

I have the following problem, I'm new in Dart, and I'm using a Future to construct a list view from a JSON response of an API, once I do this request, I receive the following response:
REQUEST:
Future<List<Job>> _fetchJobs() async {
final response = await http.get(
Uri.parse('http://10.10.10.254/httpapi.asp?command=wlanGetApListEx'));
if (response.statusCode == 200) {
final List jsonResponse = json.decode(response.body)['aplist'] as List;
print(jsonResponse);
return jsonResponse.map((job) => new Job.fromJson(job)).toList();
} else {
throw Exception('Failed to load jobs from API');
}
}
[
{
"ssid":444A446F626C65615F322E34,
"bssid":"80":"3f":"5d":"ed":"cd":f9,
"rssi":42,
"channel":8,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":426172696369632D322E3447,
"bssid":"b0":"76":"1b":"f4":"55":80,
"rssi":18,
"channel":1,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":46616D696C69615F65737061727A61,
"bssid":"60":"32":"b1":"71":"ce":46,
"rssi":0,
"channel":5,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":43617361204C756369616E61,
"bssid":"20":"ab":"48":"86":"17":58,
"rssi":0,
"channel":11,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
}
]
As you can see, the SSID values are in HEX and I need it in UTF-16 or UTF-8
I was trying to implement the hex package, but I can not find how to implement it on a JSON array like this.

The hex codex is in the convert package (not to be confused with the dart built in convert library).
If you need to convert the string you have to its ascii/utf8 form use both convert libraries like this:
import 'dart:convert';
import 'package:convert/convert.dart';
void main() {
final h = '444A446F626C65615F322E34';
final u = utf8.decode(hex.decode(h));
print(u); // prints DJDoblea_2.4
}
The more troubling issue seems to be that the data excerpt you provide is not valid JSON, so you cannot, of course, decode it with json.decode.

Try the following code:
import 'dart:convert';
import 'package:convert/convert.dart';
class Job {
Job({required this.ssid, required this.auth, required this.encry});
final String ssid;
final String auth;
final String encry;
factory Job.fromJson(Map<String, dynamic> json) {
return Job(
ssid: utf8.decode(hex.decode(json['ssid'])),
auth: json['auth'],
encry: json['encry'],
);
}
Map<String, dynamic> toMap() {
return {
'ssid': ssid,
'auth': auth,
'encry': encry,
};
}
}
final List<Map<String, dynamic>> jsonResponse = (json.decode(response.body)['aplist'] as List).map((e) => Job.fromJson(e)).map((e) => e.toMap()).toList();

Related

Read Bytes data from fetch response

I want to convert an Android-Kotlin project to React Native, and I have a problem:
The Kotlin project handle data fetch from api like that:
import java.net.URL
import java.nio.ByteBuffer
import java.nio.ByteOrder
fun getData() {
val bytes = try {
URL(address).readBytes()
} catch (e: Exception) {
return emptySet()
}
val arrayBuffer = ByteBuffer
.wrap(bytes)
.order(ByteOrder.BIG_ENDIAN)
}
return arrayBuffer
}
fun URL.readBytes(settings: HeaderSetter? = null): ByteArray {
val request = Request.Builder()
.url(this).let {
settings?.invoke(it) ?: it
}.build()
return client.newCall(request).execute().also { if (it.code() != 200) throw IOException("CODE ${it.code()}") }.body()?.use { it.bytes() } ?: throw IOException()
}
var clientHolder: OkHttpClient? = null
val client: OkHttpClient
get() = clientHolder ?: clientBuilder.build().also {
clientHolder = it
}
How I do it in react-native ?
For people arriving from search engines and looking to get an answer to the question as written in the title, the way to read bytes from a fetch response is to use Response.arrayBuffer or Response.blob.
More information can be found here: https://developer.mozilla.org/en-US/docs/Web/API/Response
Some unsolicited tips for working with array buffers:
To access individual bytes use Uint8Array - i.e. new Uint8Array(array)
To view bytes as a (a.k.a primitive hexdump) decode them as iso-8859-1 using TextDecoder - i.e. new TextDecoder("iso-8859-1")
To convert bytes to normal strings, also use TextDecoder.

String to array (object) Angular TS 12

I have a CSV file (local), converted it to a string, part of the string is like:
44,"3845657"
51,"3847489"
1,"3888510"
79,"3840471"
57,"3864492"
After I receive input number (first value), I want to match it to the second value (string).
so if input is 51, I want to be able to return 3847489.
No headers in the csv.
CSV to string:
fetchData() {
fetch('../../../assets/static/mapping.csv')
.then(response => response.text())
.then(data => {
// Do something with your data
console.log(data);
this.mappingCSV = data;
});
}
outputs:
44,"3845657"
51,"3847489"
1,"3888510"
79,"3840471"
57,"3864492"
Other ways to convert a csv to an array of objects is also welcome, not married with my csv to string method.
I'm using HTTPClient in this example which is a built-in service class available in Angular. Here's how to use HTTPClient of Angular for you to read and know its benefits.
In my .ts file, I split the text-converted csv first for any newline. Then I added a loop in which I split the text by comma and pushed the necessary details to the new csvArray.
export class SampleComponent {
public csvArr: CsvArray[] = [];
constructor(private http: HttpClient) {
this.http.get('assets/csv.csv', {
responseType: 'text'
}).subscribe(
(data) => {
const csvToRowArray = data.split('\n');
console.log(csvToRowArray);
for (let index = 0; index < csvToRowArray.length; index++) {
const row = csvToRowArray[index].split(',');
this.csvArr.push(new CsvArray(parseInt(row[0], 10), row[1]));
}
console.log(this.csvArr);
},
(error) => {
console.log(error);
}
);
}
}
export class CsvArray {
id: number;
text: string;
constructor(id: number, text: string) {
this.id = id;
this.text = text;
}
}
I created a stackblitz so that you can check my implementation.

Flutter firebase, how to retrive user data and have it on the map or a list

I saw many examples on internet, but in each case, the data is returning on a listview. I don't want to print in a listview. I want to use data in the app.
This is the way I am addind data on firebase. (I am using a class Info).
void infouser(context) async {
final db = FirebaseFirestore.instance;
final info = Info(yourname, animaName, yourmail);
final uid = await Provider.of(context).auth.getCurrentUID();
await db.collection("userData").doc(uid).collection("info").add(info.toJson());
}
I also tried with set,
createInfo(context) async {
final uid = await Provider.of(context).auth.getCurrentUID();
DocumentReference documentReference =
await FirebaseFirestore.instance.collection('Animal').doc(uid);
Map<String, dynamic> todos = {
'name': yourname,
'animalname' :animalName,
'email' : yourmail,
};
documentReference.set(todos).whenComplete(() {
print( yourname, animalName, yourmail
);
});
}
In both case, I was only able to print data on a Listview. But that is not what I want. I want to have data on a list or a map to be able to use it elsewhere in the app.
Please, I if you have a link(or give me a example of code) where I can see example, it will be appreciate.
thank you.
This is the example of retrieving data as map from firestore:
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
I advise to use https://firebase.flutter.dev/docs/firestore/usage/? documentation when working with Firebase from flutter

How to parse this JSON Array in Flutter?

I am working with Flutter and am currently trying to create a graph. I am looking to parse this JSON Array from the link below. My issue is that the information provided in the "prices" object, the values are all inside arrays themselves. I want to get those values and split them into an X and Y list but I have no idea how to accomplish this. I posted a snippet of the JSON data below.
https://api.coingecko.com/api/v3/coins/bitcoin/market_chartvs_currency=usd&days=1
I am only familiar with parsing data by creating a class and constructor. Then create a fromJSON(Map<String, dynamic> json) class and putting the data into a list, as shown in the code snippet below that I created from another URL with object values. How could I go about parsing this array JSON data into two list data?
CODE TO PARSE JSON
List<Coins> _coins = List<Coins>();
Future<List<Coins>> fetchCoins() async {
var url = 'URL';
var response = await http.get(url);
var coins = List<Coins>();
if (response.statusCode == 200) {
var coinsJSON = json.decode(response.body);
for (var coinJSON in coinsJSON) {
coins.add(Coins.fromJson(coinJSON));
}
}
return coins;
}
#override
void initState() {
fetchCoins().then((value) {
setState(() {
_coins.addAll(value);
});
});
super.initState();
}
class Coins{
String symbol;
String name;
Coins(this.symbol, this.name);
Coins.fromJson(Map<String, dynamic> json) {
symbol = json['symbol'];
name = json['name'];
JSON DATA SNIPPET
{
"prices":[
[
1566344769277,
10758.856131083012
],
[
1566345110646,
10747.91694691537
],
[
1566345345922,
10743.789313302059
],
]
}
EDIT: SOLVED WITH THE HELP OF #EJABU.
class HistoricalData {
List prices;
List<num> listX = [];
List<num> listY = [];
HistoricalData(this.prices,this.listX, this.listY);
HistoricalData.fromJson(Map<String, dynamic> json) {
prices = json['prices'];
for (var price in prices) {
listX.add(price[0]);
listY.add(price[1]);
}
}
You may try this...
New class Coins definition:
class Coins {
List<num> listX = [];
List<num> listY = [];
Coins(this.listX, this.listY);
Coins.fromJson(Map<String, dynamic> json) {
List<List<num>> prices = json['prices'];
for (var price in prices) {
listX.add(price[0]);
listY.add(price[1]);
}
}
}
Then later you can fetch it by these lines :
// Future<List<Coins>> fetchCoins() async { // Remove This
Future<Coins> fetchCoins() async {
var url = 'URL';
var response = await http.get(url);
// var coins = List<Coins>(); // Remove This
Coins coins;
if (response.statusCode == 200) {
var coinsJSON = json.decode(response.body);
// Remove This
// for (var coinJSON in coinsJSON) {
// coins.add(Coins.fromJson(coinJSON));
// }
//
coins = Coins.fromJSON(coinsJSON);
}
return coins;
}
Accessing Data in Widget
In Widgets , our expected variable resides as property inside Coins class.
For example, if you use FutureBuilder, you may use these lines:
child: FutureBuilder(
future: fetchCoins(),
builder: (_, __) {
return SomeChartWidget(
listX: coins.listX,
listY: coins.listY,
);
},
),
Generating Serializers automatically
I suggest you take a look at https://pub.dev/packages/json_serializable, which is a package that does the boilerplate code generation for you. Although it might me a bit overkill to add something like this to your code or your workflow, automatically generating serializers is very convenient.
Not that in order to have custom sub-classes, they need to provide serialization as well.
If you want to extend your knowledge even further, you can also have a look at https://pub.dev/packages/built_value and https://pub.dev/packages/built_value_generator

Byte array and JSON in [FromBody]

I am trying pass an object which consists of different data type. I am always getting null value for orderDetails in Web API.
However if do this,
purchaseOrder.Attachments = null,
in the client then orderDetails is no longer null and I have other informations like "SendEmail" and PurchaseOrderNumber.
It looks I might not be correctly set the parameter in the client (angular 2).
However testing the same Web Api method from Console app works fine and I am not getting a null value.
Do I need to separate the JSON data and byte array?
regards,
-Alan-
Models
public class Attachments
{
public int AttachmentId { get; set; }
public string FileName { get; set ;}
public byte[] FileData { get; set ;}
}
public class UpdatePurchaseOrderViewModel
{
public bool SendEmail { get; set; }
public int PurchaseOrderNumber { get; set; }
public Attachments Attachments { get; set;
}
Here is my Web API put method definition
[HttpPut("AddPurchaseOrderNumber/{purchaseOrderId}")]
public StatusCodeResult AddPurchaseOrderNumber(int purchaseOrderId, [FromBody] UpdatePurchaseOrderViewModel orderDetails)
{
try
{
var status = _service.AddPurchaseOrderNumber(purchaseOrderId, orderDetails);
if (status == 200)
_unitOfWorkAsync.SaveChanges();
else return StatusCode(status);//No Data
}
catch
{
return StatusCode(400); // Bad Request
}
return StatusCode(200);//OK
}
Typescript snippet
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept','application/json');
let options = new RequestOptions({ headers: headers });
var body = JSON.stringify(
purchaseOrder
);
var uri = 'http://localhost:33907/api/purchaseorder/addpurchaseordernumber/' + purchaseOrderId;
return this._http.put(uri, body , options)
.map((response: Response) => {
let data = response.json();
if (data) {
return true;
}
else {
return false;
}
})
Update
The orderDetails is created as below
let file = Observable.create((observer) => {
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
observer.next(fr.result);
observer.complete();
};
fr.onerror = (err) => {
observer.error(err);
}
fr.onabort = () => {
observer.error("aborted");
}
});
file.map((fileData) => {
//build the attachment object which will be sent to Web API
let attachment: Attachments = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber:this.form.controls["purchaseOrderNumber"].value * 1, //for casting purpose
Attachments: attachment
}
console.log("Loading completed");
return order;
})
When sending objects that have byte arrays as a property back and forth between a client to a WebAPI endpoint, I typically use a DTO that stores the property to explicitly define it as a Base64 string. On the server side I map the DTO to my entity by converting the Base64 string to / from the byte array for server side operations and storing in the database.
The serializer will do something like this automatically but the format passed from JavaScript may not match what the WebAPI JSON serializer is expecting (which is why it's working from your C# Console App).
You didn't include how you are creating the purchaseOrder object in your JavaScript so I can't comment on how that object is being setup - which may be where your issue is.

Resources