Serializing scalar JSON in Flutter's Ferry Graphql for flexible Query - json

I have the following JSON scalar:
"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSON
which I am trying to convert since my query is accepting input: JSON. When testing using graphql playground, query is JSON object thus the following works:
query {
carts(where: {
owner:{id: "xxx"}
store:{name: "yyy"}
}) {
id
}
}
# query is the starting from the where: {...}
# build.yaml
# build.yaml
gql_build|schema_builder: #same for gql_build|schema_builder + gql_build|var_builder + ferry_generator|req_builder:
options:
type_overrides:
DateTime:
name: DateTime
JSON:
name: BuiltMap<String, dynamic>
import: 'package:built_collection/built_collection.dart'
gql_build|serializer_builder:
enabled: true
options:
schema: myapp|lib/graphql/schema.graphql
custom_serializers:
- import: 'package:myapp/app/utils/builtmapjson_serializer.dart'
name: BuiltMapJsonSerializer
This is the custom serializer (builtmapjson_serializer.dart)
//// lib/app/utils/builtmapjson_serializer.dart
import 'package:built_collection/built_collection.dart';
import "package:gql_code_builder/src/serializers/json_serializer.dart";
class BuiltMapJsonSerializer extends JsonSerializer<BuiltMap<String, dynamic>> {
#override
BuiltMap<String, dynamic> fromJson(Map<String, dynamic> json) {
print('MyJsonSerializer fromJson: $json');
return BuiltMap.of(json);
}
#override
Map<String, dynamic> toJson(BuiltMap<String, dynamic> operation) {
print('MyJsonSerializer toJson: ${operation.toString()}');
return operation.asMap();
}
}
and the usage:
Future testQuery() async {
Map<String, dynamic> queryMap = {
"where": {
"owner": {
"id": "xxx",
"store": {"name": "yyy"}
}
}
};
final req = GFindCartsReq((b) {
return b..vars.query.addAll(queryMap);
});
var resStream = _graphQLService.client.request(req);
var res = await resStream.first;
print(
'linkExceptions: ${res.linkException}'); // Map: LinkException(Bad state: No serializer for '_InternalLinkedHashMap<String, Map<String, Object>>'.)
}
So whenever I try to query, it is throwing the linkException stated in the comment on the last line of usage. Any idea what should be the way of serializing it?

// Write query like this
query FindCarts($owner_id: String!, $store_name: String!) {
carts(where: {
owner:{id: $owner_id}
store:{name: $store_name}
}) {
id
}
}
// And make request like this:
final req = GFindCartsReq((b) => b..vars.store_name = 'XXX'..vars.owner_id = 'YYY');
I think you may be misunderstanding the use case. they are there to serialize and deserialize the response if you want to end up with a Dart object that's different from graphql representation. you may want to try rereading this section:
https://ferrygraphql.com/docs/custom-scalars/#create-a-custom-serializer
in the example in the docs, the graphql schema returns an int for the timestamp, but we want to actually use a Date object, so that's the purpose of the serializer. it tells ferry to deserialize the int in our responses to a Date so we can use a Date in our dart code. you could still use a json serializer (like in the examples you linked to) but it still would not be in the way you're trying to use it -- it would be if your schema returns a json string and you want to deserialize the json string. for example, in my case, my graphql schema actually does return a "jsonb" type on some objects. in order to handle that, i'm using built_value's default json_object like this:
(
...
type_overrides:
jsonb:
name: JsonObject
import: "package:built_value/json_object.dart"
custom_serializers:
- import: "package:built_value/src/json_object_serializer.dart"
name: JsonObjectSerializer

Related

Make Json Model for API Call Xml2Json

I am calling an Api that returns data in XMl
I then convert it from XML to Json using Xml2Json, to then decode and acheive a JsonMap, which is returning a map well.
When I then go to do locations.fromJson to be able to call data from my model is is returning as null.
I guess converting from XML may complicate but I have tried all possibilities, parsing the entire response, the section I need and modifying the model in all the ways I could.
The data is returning fine as Json, but there is just some disconnect when parsing it with my model, made via quicktype.io
When I call it in any way, be it print or a data retrieval, it returns on null at vehicleActivity
The call
Future<Locations> fetchLiveLocations() async {
var client = http.Client();
var locations;
Xml2Json xml2Json = new Xml2Json();
try{
var response = await client.get(
'https_call');
if (response.statusCode == 200) {
xml2Json.parse(response.body);
var jsonString = xml2Json.toGData();
var jsonMap = json.decode(jsonString);
//jsonMap is returning fine
locations = Locations.fromJson(jsonMap);
//Returning as null
}
} catch(Exception) {
return locations;
}
return locations;
}
Top part of Json Model
import 'dart:convert';
Locations locationsFromJson(String str) => Locations.fromJson(json.decode(str));
String locationsToJson(Locations data) => json.encode(data.toJson());
class Locations {
Locations({
this.vehicleActivity,
});
List<VehicleActivity> vehicleActivity;
factory Locations.fromJson(Map<String, dynamic> json) => Locations(
vehicleActivity: List<VehicleActivity>.from(json["VehicleActivity"].map((x) => VehicleActivity.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"VehicleActivity": List<dynamic>.from(vehicleActivity.map((x) => x.toJson())),
};
}
class VehicleActivity {
VehicleActivity({
this.recordedAtTime,
this.itemIdentifier,
this.validUntilTime,
this.monitoredVehicleJourney,
this.extensions,
});
DateTime recordedAtTime;
String itemIdentifier;
DateTime validUntilTime;
MonitoredVehicleJourney monitoredVehicleJourney;
Extensions extensions;
factory VehicleActivity.fromJson(Map<String, dynamic> json) => VehicleActivity(
recordedAtTime: DateTime.parse(json["RecordedAtTime"]),
itemIdentifier: json["ItemIdentifier"],
validUntilTime: DateTime.parse(json["ValidUntilTime"]),
monitoredVehicleJourney: MonitoredVehicleJourney.fromJson(json["MonitoredVehicleJourney"]),
extensions: Extensions.fromJson(json["Extensions"]),
);
XML File Returned
<Siri xmlns="http://www.siri.org.uk/siri" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.siri.org.uk/siri http://www.siri.org.uk/schema/2.0/xsd/siri.xsd" version="2.0">
<ServiceDelivery>
<ResponseTimestamp>2021-12-03T18:11:05.408806+00:00</ResponseTimestamp>
<ProducerRef>ItoWorld</ProducerRef>
<VehicleMonitoringDelivery>
<ResponseTimestamp>2021-12-03T18:11:05.408806+00:00</ResponseTimestamp>
<RequestMessageRef>5747b24f</RequestMessageRef>
<ValidUntil>2021-12-03T18:16:05.408806+00:00</ValidUntil>
<ShortestPossibleCycle>PT5S</ShortestPossibleCycle>
<VehicleActivity>
<RecordedAtTime>2021-12-03T18:10:01+00:00</RecordedAtTime>
<ItemIdentifier>ad2c7031-ceac-4e7c-bc0c-9e667ad00dfe</ItemIdentifier>
<ValidUntilTime>2021-12-03T18:16:05.408968</ValidUntilTime>
<MonitoredVehicleJourney>
<LineRef>4</LineRef>
<DirectionRef>inbound</DirectionRef>
<FramedVehicleJourneyRef>
<DataFrameRef>2021-12-03</DataFrameRef>
<DatedVehicleJourneyRef>4_20211203_18_04</DatedVehicleJourneyRef>
</FramedVehicleJourneyRef>
<PublishedLineName>4</PublishedLineName>
<OperatorRef>FTVA</OperatorRef>
<DestinationRef>03700324</DestinationRef>
<VehicleLocation>
<Longitude>-0.719601</Longitude>
<Latitude>51.520305</Latitude>
</VehicleLocation>
<Bearing>30.0</Bearing>
<BlockRef>801312</BlockRef>
<VehicleRef>69921</VehicleRef>
</MonitoredVehicleJourney>
<Extensions>
<VehicleJourney>
<Operational>
<TicketMachine>
<TicketMachineServiceCode>B4</TicketMachineServiceCode>
<JourneyCode>1815</JourneyCode>
</TicketMachine>
</Operational>
<VehicleUniqueId>69921</VehicleUniqueId>
<DriverRef>801312</DriverRef>
</VehicleJourney>
</Extensions>
</VehicleActivity>
Here's an example VehicleActivity class - note that it doesn't handle any errors like missing XML tags or unparsable dates, which you should add yourself.
class VehicleActivity {
VehicleActivity({
this.recordedAtTime,
this.itemIdentifier,
this.validUntilTime,
});
DateTime? recordedAtTime;
String? itemIdentifier;
DateTime? validUntilTime;
factory VehicleActivity.fromElement(XmlElement vaElement) => VehicleActivity(
recordedAtTime: DateTime.parse(
vaElement.findElements('RecordedAtTime').first.text,
),
itemIdentifier: vaElement.findElements('ItemIdentifier').first.text,
validUntilTime: DateTime.parse(
vaElement.findElements('ValidUntilTime').first.text,
),
);
}
You would use the factory method from the enclosing tag (similar to how your JSON parsers are written), for each of the vehicle activity tags it finds. (Note that XML can have multiple identically named tags, which is why the code is using first to find the (hopefully) one and only tag. If you want to parse XML correctly you need to deal with this - and note that the trip through JSON could break this - but not with your simple schema.)
Here's a simple example that just finds all the vehicle activity tags:
final doc = XmlDocument.parse(utf8.decode(response.bodyBytes));
final allActivities = doc
.findAllElements('VehicleActivity')
.map((e) => VehicleActivity.fromElement(e))
.toList();
print(allActivities);

Flutter : How to parse JSON Array of objects

Can anyone tell me how to parse arrays of object in flutter. When I am parsing the json I am getting error as List is not a subtype of type Map<String, dynamic>.
Below is my json file which needs to be parsed. Please help me to fix this issue.
[
{
"empPayslipsId": "2021012000440",
"month": "Jan",
"description": "Payslip for JAN 2021 (Month End)",
"paymentPeriod": "1/1/2021 12:00:00 AM - 1/31/2021 12:00:00 AM",
"lastAccessBy": "0002\r\n118.200.199.70",
"lastAccessDate": "20210202",
"lastAccessTime": "105706",
"successAccess": "2",
"failAccess": "2"
}
]
Future<void> loadQueryPeriod(int year, var month) async {
String baseURL = '${domainURL}api/PaySlip?year=$year&month=$month';
try {
final response = await http.get(baseURL, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization':
'Bearer ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}',
});
print('UIC PDF response : ${response.body}');
print(
'UIC Token response : ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}');
if (response.statusCode == 200) {
final Map<String, dynamic> data = json.decode(response.body);
print('result type: ${data.runtimeType}');
}
} catch (e) {
print(e);
throw Exception('Download PDF Fail! ${e.toString()}');
}
}
}
Change it to this:
final Map<String, dynamic> data = json.decode(response.body)[0];
This is because your map is inside a list. Look at the square brackets [ ] enclosing your map. The map that you need, is at index[0] of this list.
use this podo class :
// Generated by https://quicktype.io
// To parse this JSON data, do
//
// final sample = sampleFromJson(jsonString);
import 'dart:convert';
List<Sample> sampleFromJson(String str) {
final jsonData = json.decode(str);
return new List<Sample>.from(jsonData.map((x) => Sample.fromJson(x)));
}
String sampleToJson(List<Sample> data) {
final dyn = new List<dynamic>.from(data.map((x) => x.toJson()));
return json.encode(dyn);
}
class Sample {
String empPayslipsId;
String month;
String description;
String paymentPeriod;
String lastAccessBy;
String lastAccessDate;
String lastAccessTime;
String successAccess;
String failAccess;
Sample({
this.empPayslipsId,
this.month,
this.description,
this.paymentPeriod,
this.lastAccessBy,
this.lastAccessDate,
this.lastAccessTime,
this.successAccess,
this.failAccess,
});
factory Sample.fromJson(Map<String, dynamic> json) => new Sample(
empPayslipsId: json["empPayslipsId"],
month: json["month"],
description: json["description"],
paymentPeriod: json["paymentPeriod"],
lastAccessBy: json["lastAccessBy"],
lastAccessDate: json["lastAccessDate"],
lastAccessTime: json["lastAccessTime"],
successAccess: json["successAccess"],
failAccess: json["failAccess"],
);
Map<String, dynamic> toJson() => {
"empPayslipsId": empPayslipsId,
"month": month,
"description": description,
"paymentPeriod": paymentPeriod,
"lastAccessBy": lastAccessBy,
"lastAccessDate": lastAccessDate,
"lastAccessTime": lastAccessTime,
"successAccess": successAccess,
"failAccess": failAccess,
};
}
Now inorder to parse json call,
Sample sample = sampleFromJson(jsonString);
via this you will get the access to sample PODO class and you can access any object you want.
The initial data you received by calling a get request isn't stored in a map, but rather in a list.
You should do something like this to receive your initial data.
if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
}
From there, they're numerous ways to get the data from your data variable. You can use lists here if you want, for example to get the value of month in the JSON.
final String month = data[0]['month'];
If you'd prefer to use Maps, the syntax it'll look like this
final Map<String, dynamic> endpointData = data[0];
final String responseKey = 'month';
final var result = endpointData[responseKey];
if you have data model you can do it like this
fromJsonList(List<dynamic> jsonList) {
List<YourModel> yourModelList = [];
jsonList.forEach((jsonModel) {
menuModelsOfferList.add(YourModel.fromJson(jsonModel));
});

Kafka Streams API GroupBy behaviour

I am new in kafka streams and I am trying to aggregate some streaming data into a KTable using groupBy function. The problem is the following:
The produced message is a json msg with the following format:
{ "current_ts": "2019-12-24 13:16:40.316952",
"primary_keys": ["ID"],
"before": null,
"tokens": {"txid":"3.17.2493",
"csn":"64913009"},
"op_type":"I",
"after": { "CODE":"AAAA41",
"STATUS":"COMPLETED",
"ID":24},
"op_ts":"2019-12-24 13:16:40.316941",
"table":"S_ORDER"}
I want to isolate the json field "after" and then create a KTable with "key" = "ID" and value the whole json "after".
Firstly, I created a KStream to isolate the "after" json, and it works fine.
KStream code block: (Don't pay attention to the if statement because "before" and "after" have the same format.)
KStream<String, String> s_order_list = s_order
.mapValues(value -> {
String time;
JSONObject json = new JSONObject(value);
if (json.getString("op_type").equals("I")) {
time = "after";
}else {
time = "before";
}
JSONObject json2 = new JSONObject(json.getJSONObject(time).toString());
return json2.toString();
});
The output, as expected, is the following:
...
null {"CODE":"AAAA48","STATUS":"SUBMITTED","ID":6}
null {"CODE":"AAAA16","STATUS":"COMPLETED","ID":1}
null {"CODE":"AAAA3","STATUS":"SUBMITTED","ID":25}
null {"CODE":"AAAA29","STATUS":"SUBMITTED","ID":23}
...
Afterwards, I implement a KTable to groupBy the "ID" of the json.
KTable code block:
KTable<String, String> s_table = s_order_list
.groupBy((key, value) -> {
JSONObject json = new JSONObject(value);
return json.getString("ID");
});
And there is an error that I want to create KTable<String, String> but I am creating GroupedStream<Object,String>.
Required type: KTable<String,String>
Provided:KGroupedStream<Object,String>
no instance(s) of type variable(s) KR exist so that KGroupedStream<KR, String> conforms to KTable<String, String>
In conclusion, the question is what exactly are KGroupedStreams and how to implement a KTable properly ?
After groupBy processor, you can use a stateful processor, like aggregate or reduce (that processors returns KTable). You can do something like this:
KGroupedStream<String, String> s_table = s_order_list
.groupBy((key, value) ->
new JSONObject(value).getString("ID"),
Grouped.with(
Serdes.String(),
Serdes.String())
);
KTable<String, StringAggregate> aggregateStrings = s_table.aggregate(
(StringAggregate::new),
(key, value, aggregate) -> aggregate.addElement(value));
StringAggregate looks like:
public class StringAggregate {
private List<String> elements = new ArrayList<>();
public StringAggregate addElement(String element){
elements.add(element);
return this;
}
//other methods
}

how to update json data using flutter

how to update JSON value. I am using flutter with a REST API to change the data but I'm struggling how to refresh my JSON data sorry friends I don't know much about the flutter so please help me out about it please find JSON'S Object below:
{
id: 1,
clef: "Y8F5eEo0",
IndiceSensibilite: "0.04",
Objectif: "1.00"
}
I want to update the value of IndiceSensibilite using a textField.
I m here for more clarification.
i will be very thankful if there's someone who gonna help me.
You can transform the JSON into an Object, make your modifications and back to JSON:
import 'dart:convert'; // make sure you imported this library
String jsonValue = '{"id": 1, "clef": "Y8F5eEo0", "indiceSensibilite": "0.04", "objectif": "1.00" }'; // original JSON
Use a Future to convert it into Object:
Future<ToObject> jsonToObject() async {
var parse = json.decode(jsonValue);
return ToObject.parseJson(parse);
}
and your Object (ToObject in my case) will have the following model and methods:
class ToObject {
int id;
String clef;
String indiceSensibilite;
String objectif;
ToObject({this.id, this.clef, this.indiceSensibilite, this.objectif});
factory ToObject.parseJson(Map<String, dynamic> json) => ToObject(
id: json['id'], clef: json['clef'], indiceSensibilite: json['indiceSensibilite'], objectif: json['objectif']);
Map<String, dynamic> toJson() =>
{'id': id, 'clef': clef, 'indiceSensibilite': indiceSensibilite, 'objectif': objectif};
}
I used a FutureBuilder to get the data, modify the value and back to JSON:
FutureBuilder<ToObject>(
future: jsonToObject(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var object = snapshot.data;
object.indiceSensibilite = "43.00";
return Text(json.encode(object.toJson()));
} else {
return Text("Loading...");
}
},
)
Your end result is a modified JSON to use as you wish:

Angular 4 - Typescript: json2typescript json key mapper

Sorry but I didn't explain it very well. I edit my question again:
I have an angular 4 application and I use json2typescript to convert from json to object and vice versa but I have a problem because I have a class structure and the response json from an external api has another structure. Example:
Customer {
#JsonProperty('idCardNumber', String)
idCardNumber: string = undefined;
#JsonProperty('rolInfo.name',String)
name: string = undefined;
#JsonProperty('rolInfo.surname',String)
surname: string = undefined;
}
External Json API Reponse:
{
"idCardNumber": "08989765F",
"rolInfo": {
"name": "John"
"surname: "Smith"
}
}
So, I would like to map from the json above to my Customer object and not to change my structure. I tried to put 'rolInfo.name' into the JsonProperty, but that doesn't work.
Change your Customer class to something like below
Customer {
#JsonProperty('idCardNumber', String)
idCardNumber: string = undefined;
#JsonProperty('rolInfo', Any)
rolInfo: any = {}; // if you set this to undefined, handle it in getter/setter
get name(): string {
return this.rolInfo['name'];
}
set name(value: string) {
this.rolInfo['name'] = value;
}
get surname(): string {
return this.rolInfo['surname'];
}
set surname(value: string) {
this.rolInfo['surname'] = value;
}
}
That should do it
Seems like the response JSON is already in a good format and you don’t need to do the conversion.
I would recommend creating models as they allow for serialization and deserialization when making API calls and binding the response to that model.