Making DataModel from non empty json gives null - dart

There is a model
class DataModel {
String name;
String img;
int price;
int people;
int stars;
String description;
String location;
DataModel({
required this.name,
required this.img,
required this.price,
required this.people,
required this.stars,
required this.description,
required this.location,
});
factory DataModel.fromJson(Map<String, dynamic> json) {
return DataModel(
name: json['name'],
img: json['img'],
price: json['price'],
people: json['people'],
stars: json['stars'],
description: json['description,'],
location: json['location'],
);
}
}
and a function where I get null
import 'dart:convert';
import 'package:flutter_cubit/services/data_model.dart';
import 'package:http/http.dart' as http;
class DataServices {
String baseUrl = 'http://******';
Future<List<DataModel>> getInfo() async {
String apiUrl = '/****';
http.Response res = await http.get(Uri.parse(baseUrl + apiUrl));
try {
print('response status:${res.statusCode}');
if (res.statusCode == 200) {
print('----------1');
List<dynamic> list = json.decode(res.body);
print(list[0]); // only first imem just for example the data isn't empty
print('----------2');
// the error is on the next line
List<DataModel> result = list.map((e) => DataModel.fromJson(e)).toList();
print('----------3');
print(result);
return result;
} else {
return <DataModel>[];
}
} catch (e) {
print(e);
return <DataModel>[];
}
}
}
The output from the above function
I/flutter ( 6979): response status:200
I/flutter ( 6979): ----------1
I/flutter ( 6979): {id: 1, name: British Columbia, description: This 134 kilometers Highway 99 trail gives you a taste of the Canada mountains, from Horseshoe Bay in the north of Vancouver to Pemberton. , price: 1276, stars: 4, people: 5, selected_people: 5, img: images/f9d4b5e088c7bc70b7bbd51cd89e71b6.jpeg, location: Canada, British Columbia, created_at: 2021-11-17T10:09:08.000000Z, updated_at: 2021-11-19T13:39:55.000000Z}
I/flutter ( 6979): ----------2
I/flutter ( 6979): type 'Null' is not a subtype of type 'String'
Why do I get null on error-line of the code?
the original json from api
[
{
"id":1,
"name":"British Columbia",
"description":"This 134 kilometers Highway 99 trail gives you a taste of the Canada mountains, from Horseshoe Bay in the north of Vancouver to Pemberton. ",
"price":1276,
"stars":4,
"people":5,
"selected_people":5,
"img":"images\/f9d4b5e088c7bc70b7bbd51cd89e71b6.jpeg",
"location":"Canada, British Columbia",
"created_at":"2021-11-17T10:09:08.000000Z",
"updated_at":"2021-11-19T13:39:55.000000Z"
},
{
"id":2,
"name":"Icefields",
"description":"This stretches for a straight 234 kilometers from Banff to Jasper. The Icefields Parkway offers you the picturesque panorama of Alberta\u2019s most talked about mountain vistas. ",
"price":2153,
"stars":5,
"people":5,
"selected_people":3,
"img":"images\/1a2d25d3c5ea7912982e37b8005bbebe.jpeg",
"location":"Icefields, Alberta",
"created_at":"2021-11-17T10:10:43.000000Z",
"updated_at":"2021-11-19T14:18:09.000000Z"
},
{
"id":3,
"name":"Moraine Lake",
"description":"Moraine Lake is yet another astonishing geographical location that you cannot afford to miss out on if you\u2019re traveling along the Icefields Parkway. ",
"price":3456,
"stars":3,
"people":5,
"selected_people":4,
"img":"images\/9a4079ae9e67ca51b9fdf4670a5795f4.jpeg",
"location":"Moraine Lake, Alberta",
"created_at":"2021-11-17T10:16:31.000000Z",
"updated_at":"2021-11-19T13:40:36.000000Z"
},
{
"id":4,
"name":"Ontario",
"description":"If you\u2019re in Canada and if you\u2019re a sucker for mountains, Killarney Provincial Park in Ontario is your best catch for Canada mountains near Toronto. ",
"price":3312,
"stars":4,
"people":5,
"selected_people":3,
"img":"images\/24fe838b325456a0ca7fc2249409de3f.jpeg",
"location":"Killarney Provincial Park",
"created_at":"2021-11-17T10:18:46.000000Z",
"updated_at":"2021-11-19T13:40:44.000000Z"
},
{
"id":5,
"name":"Gaza",
"description":"Dome of the rock the beautiful and amazing human made architectural.",
"price":10,
"stars":5,
"people":5,
"selected_people":4,
"img":"images\/9aaf2377eb3e0978ecb0e17717579a2b.jpg",
"location":"Palestine, Gaza",
"created_at":"2021-12-08T12:29:53.000000Z",
"updated_at":"2021-12-08T12:29:53.000000Z"
}
]

There is a mistake in your factory Constructor
factory DataModel.fromJson(Map<String, dynamic> json) {
return DataModel(
name: json['name'],
img: json['img'],
price: json['price'],
people: json['people'],
stars: json['stars'],
description: json['description,'], //Here; You added a comma.
location: json['location'],
);
}
Use this:
factory DataModel.fromJson(Map<String, dynamic> json) {
return DataModel(
name: json['name'],
img: json['img'],
price: json['price'],
people: json['people'],
stars: json['stars'],
description: json['description'], //Comma removed.
location: json['location'],
);
}

Related

Apple Pay using #stripe/stripe-react-native is not working showing some hook call error

When i am trying to implement Apple Pay using #stripe/stripe-react-native then is not working showing some hook call , Code & Error showing below:
import { StripeProvider, useApplePay} from '#stripe/stripe-react-native';
const { presentApplePay, confirmApplePayPayment } = useApplePay();
export default class App (){
handlePayPress = async () => {
const {error, paymentMethod} = await presentApplePay({
cartItems: [
{
label: 'payment label',
amount: '50', // amount as string
type: 'final',
},
],
country: 'US', // enter any country code supported by stripe,
currency: 'USD', // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const {error: confirmApplePayError} = await confirmApplePayPayment(
clientSecret,
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert('Success', 'The payment was confirmed successfully!');
}
}
};
...
...
}
You can create a seperate functional component for that and call in your class component like this
export default class App (){
render() {
return(
<ApplePayFunction data={'your data here'}/>
);
}
}
export default function ApplePayFunction(props) {
const { presentApplePay, confirmApplePayPayment } = useApplePay();
const handlePayPress = async () => {
const { error, paymentMethod } = await presentApplePay({
cartItems: [
{
label: "payment label",
amount: "50", // amount as string
type: "final",
},
],
country: "US", // enter any country code supported by stripe,
currency: "USD", // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const { error: confirmApplePayError } = await confirmApplePayPayment(
clientSecret
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert("Success", "The payment was confirmed successfully!");
}
}
};
// Return UI Views below
return null;
}
Hooks must always be called inside functional components. Code refactor for reference.
import { StripeProvider, useApplePay } from "#stripe/stripe-react-native";
export default function App() {
const { presentApplePay, confirmApplePayPayment } = useApplePay();
const handlePayPress = async () => {
const { error, paymentMethod } = await presentApplePay({
cartItems: [
{
label: "payment label",
amount: "50", // amount as string
type: "final",
},
],
country: "US", // enter any country code supported by stripe,
currency: "USD", // enter any currency supported by stripe,
});
if (error) {
Alert.alert(error.code, error.message);
} else {
const { error: confirmApplePayError } = await confirmApplePayPayment(
clientSecret
);
confirmApplePayPayment(clientSecret);
if (confirmApplePayError) {
Alert.alert(confirmApplePayError.code, confirmApplePayError.message);
} else {
Alert.alert("Success", "The payment was confirmed successfully!");
}
}
};
// Return UI Views below
return null;
}

NestJS Mapped Typed - Nested objects

In NestJS I want to use PickType() with a class, which has nested class properties.
Example:
export class Product {
status: string;
payment: {
status: string;
type: string;
}
}
It should result in the swagger documentation as following DTO:
class PartialClass {
payment: {
status: string,
type: string
}
}
But the following implementation does not work:
class PartialClass {
#ApiProperty({
type: () => PickType(Videochat, ['payment']),
})
payment: Pick<Videochat['payment'], 'type' | 'status'>;
}
It returns an empty payment class property:
class PartialClass {
payment: {
}
}
So i guess PickType can't handle nested Types.
I tried also:
type: () => PickType(PickType(Videochat, ['payment']), ['status', 'type'])
but it also not working.
You can handle it this way, let's assume we have the following class:
type User = {
id: number,
name: string,
address: {
street: string,
zipcode: string,
geo: {
lat: string,
lng: string,
},
},
};
to pick user with address you can simply do type UserWithOnlyAddress = Pick<User, 'address'>;
in case you have to pick user with address's street only you can handle it:
type Pick2<T, K1 extends keyof T, K2 extends keyof T[K1]> = {
[P1 in K1]: {
[P2 in K2]: (T[K1])[P2];
};
};
type UserWithOnlyStreetAddress = Pick2<User, 'address', 'street'>;
And for picking at three levels
type UserWithOnlyGeoLat = Pick3<User, 'address', 'geo', 'lat'>;
type User = {
id: number,
name: string,
address: {
street: string,
zipcode: string,
geo: {
lat: string,
lng: string,
},
},
};
type Pick3<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]> = {
[P1 in K1]: {
[P2 in K2]: {
[P3 in K3]: ((T[K1])[K2])[P3];
};
};
};

how to optimisticResponse a connection property in relay modern mutation?

i have a comments connection in a mutation, this is the query:
export default mutationFromQuery(graphql`
mutation AddBookMutation($input: AddBookInput! $count: Int $cursor: String ) {
addBook(input: $input) {
book {
__typename
cursor
node {
id
title
owner
createdAt
comments(first: $count, after: $cursor)
#connection(key: "BookComments_comments", filters: []) {
__typename
edges {
node {
id
}
}
}
}
}
}
}
`)
This is how i did my optimisticUpdater that don't work:
optimisticUpdater: (store) => {
const userProxy = store.get(viewerId)
const owner = userProxy.getValue('username')
const id = uuidv1();
const book = store.create(id, 'Book');
book.setValue(id, 'id');
book.setValue(bookTitle, 'title');
book.setValue(owner, 'owner');
book.setValue(Date.now(), 'createdAt');
const comments = store.create(uuidv1(), 'comments')
comments.setLinkedRecords([], 'edges')
const pageInfo = store.create(uuidv1(), 'pageInfo')
pageInfo.setValue(null, 'endCursor')
pageInfo.setValue(false, 'hasNextPage')
pageInfo.setValue(false, 'hasPreviousPage')
pageInfo.setValue(null, 'startCursor')
comments.setLinkedRecord(pageInfo, 'pageInfo')
book.setLinkedRecord(comments, 'comments')
const bookEdge = store.create(uuidv1(), 'BookEdge');
bookEdge.setLinkedRecord(book, 'node');
console.log('bookEdge ', bookEdge)
booksUpdater(userProxy, bookEdge);
},
The problem i have is that comments always ends up on undefined as you can see above i've already set it. I also did this but i am still not getting an optimistic UI:
optimisticResponse: {
addBook: {
book: {
__typename: 'BookEdge',
cursor: uuidv1(),
node: {
id: uuidv1(),
title: bookTitle,
owner: username,
createdAt: Date.now(),
comments: {
__typename: 'CommentConnection',
edges: [],
pageInfo: {
endCursor: null,
hasNextPage: false
}
}
}
}
}
},
App don't crash with optimisticResponse code but no optimistic UI effect, but with the optimisticUpdater it's crashing with comments being undefined, for now I am settling with my updater:
updater: (store) => {
const userProxy = store.get(viewerId)
const payload = store.getRootField('addBook');
booksUpdater(userProxy, payload.getLinkedRecord('book'));
},
since the comments is undefined I guess we cannot use this for optimistic effect:
const comments = store.create(uuidv1(), 'comments')
comments.setLinkedRecords([], 'edges')
book.setLinkedRecord(comments, 'comments')
on my Book, this is the query which has the comments fragment that is undefined on optimistic update with the code above:
export default createRefetchContainer(
BookItem,
{
book: graphql`
fragment BookItem_book on Book
#argumentDefinitions(
count: { type: "Int", defaultValue: 5 }
cursor: { type: "String", defaultValue: null }
) {
id
title
owner
createdAt
...BookComments_book
}
`
},
graphql`
query BookItemQuery($id: ID!, $count: Int, $cursor: String) {
book: node(id: $id) {
...BookItem_book #arguments(count: $count, cursor: $cursor)
}
}
`
);
and now the query for the comments component where it gets the book.comments.edges is undefined:
export default createPaginationContainer(
BookComments,
{
book: graphql`
fragment BookComments_book on Book
#argumentDefinitions(
count: { type: "Int", defaultValue: 3 }
cursor: { type: "String", defaultValue: null }
) {
id
title
comments(first: $count, after: $cursor)
#connection(key: "BookComments_comments", filters: []) {
__typename
edges {
node {
id
text
owner
createdAt
}
}
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
}
}
}
`
},
{
direction: 'forward',
getConnectionFromProps: (props) => props.book && props.book.comments,
getFragmentVariables: (prevVars, totalCount) => ({
...prevVars,
count: totalCount
}),
getVariables: (props, { count, cursor }, _fragmentVariables) => ({
count,
cursor,
id: props.book.id
}),
query: graphql`
query BookCommentsQuery($id: ID!, $count: Int, $cursor: String) {
book: node(id: $id) {
...BookComments_book #arguments(count: $count, cursor: $cursor)
}
}
`
}
);
maybe this is an anti pattern? but i just wanted to have a optimistic effect for this
Some things are still not very clear to me about how those components and queries work, so I'll update this answer later. (I don't know if you want to return new book optimistically from node() query or add it to some list/connection of books)
Please check if I used correct type names (CommentConnection / CommentsConnection, etc)
optimisticUpdater: (store) => {
const userProxy = store.get(viewerId)
const owner = userProxy.getValue('username')
const commentsParams = { // must be same keys and values as in comments(first: $count, after: $cursor)
first: count,
after: cursor
}
// Create Book
const id = uuidv1();
const book = store.create(id, 'Book');
book.setValue(id, 'id');
book.setValue(bookTitle, 'title');
book.setValue(owner, 'owner');
book.setValue(Date.now(), 'createdAt');
// Create comments connection
const comments = store.create(uuidv1(), 'CommentConnection')
comments.setLinkedRecords([], 'edges')
// Create PageInfo
const pageInfo = store.create(uuidv1(), 'PageInfo')
pageInfo.setValue(null, 'endCursor')
pageInfo.setValue(false, 'hasNextPage')
pageInfo.setValue(false, 'hasPreviousPage')
pageInfo.setValue(null, 'startCursor')
// Link created records
comments.setLinkedRecord(pageInfo, 'pageInfo')
book.setLinkedRecord(comments, 'comments', commentsParams) // don't forget commentsParams with same values as are used in comments graphql query
// I'm not sure about this final part, because I don't really get how that app works, but if you want this book to show as optimistic response for `node(id: $id)`, you'll do something like this:
store.getRoot().setLinkedRecord(book, 'node', { id: id }) // same id as used in BookItemQuery
}

Parsing Json in flutter

I am learning flutter and trying to parse a json which is array or json objects like this.
[
{
"albumId": 1,
"id": 1,
"title": "accusamus beatae ad facilis cum similique qui sunt",
"url": "https://via.placeholder.com/600/92c952",
"thumbnailUrl": "https://via.placeholder.com/150/92c952"
},
{
"albumId": 1,
"id": 2,
"title": "reprehenderit est deserunt velit ipsam",
"url": "https://via.placeholder.com/600/771796",
"thumbnailUrl": "https://via.placeholder.com/150/771796"
},]
And here is my fetch function which fetches this data from server.
fetch() async{
var client = new http.Client();
try {
var uriResponse = await
client.get('https://jsonplaceholder.typicode.com/photos');
if(uriResponse.statusCode == 200){
var data = json.decode(uriResponse.body);//data is array of objects
List<Photo> pics= data.map((Map<String,dynamic> model)=> Photo.fromJson(model)).toList();
setState(() {
photos = data;
_isLoading = false;
});
}
} finally {
client.close();
}
}
But the line ;
List<Photo> pics= data.map((Map<String,dynamic> model)=> Photo.fromJson(model)).toList();
gives me error that:
ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: type '(Map<String, dynamic>, dynamic) => Photo' is not a subtype of type '(dynamic) => dynamic' of 'f'
Here is my Photo PODO class.
class Photo {
final int id;
final String title;
final String url;
final String thumbnailUrl;
Photo({this.id, this.title,this.url, this.thumbnailUrl});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'] as int,
title: json['title'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
url: json['url'] as String,
);
}
}
What i am doing wrong in the above code? Thanx in advance !
You can use quicktype it lets you copy in your JSON string and generates the Dart Objects
In my project I have done like this and its working
pics = (data as List).map((model) => Photo.fromJson(model)).toList();
Try using
pics = data.map((i)=>Photo.fromJson(i)).toList();
You are receiving an json array and not json object from server
try this if it didnt work make sure to print the the response body
Iterable<dynamic> l = json.decode(uriResponse.body);
List<Post> posts = l.map((model) => Post.fromJson(model)).toList();

Unknown type on deserialization. Need either specifiedType or discriminator field

I have following json
{
"status": 1,
"msg": "Success",
"data": {
"getFeeCount": [
{
"yearId": "1",
"yearName": "FY 2017-18"
},
{
"yearId": "2",
"yearName": "FY 2018-19"
}
],
"getFeeCat": [
{
"fee_cat_id": "1",
"fee_cat_name": "1st Semester Tuition Fee"
},
{
"fee_cat_id": "2",
"fee_cat_name": "2nd Semester Tuition Fee"
},
{
"fee_cat_id": "3",
"fee_cat_name": "3rd Semester Tuition Fee"
},
{
"fee_cat_id": "4",
"fee_cat_name": "4th Semester Tuition Fee"
},
{
"fee_cat_id": "5",
"fee_cat_name": "5th Semester Tuition Fee"
},
{
"fee_cat_id": "6",
"fee_cat_name": "6th Semester Tuition Fee"
},
{
"fee_cat_id": "7",
"fee_cat_name": "7th Semester Tuition Fee"
},
{
"fee_cat_id": "8",
"fee_cat_name": "8th Semester Tuition Fee"
},
{
"fee_cat_id": "9",
"fee_cat_name": "Certification Fee Year 1"
},
{
"fee_cat_id": "10",
"fee_cat_name": "Certification Fee Year 2"
},
{
"fee_cat_id": "11",
"fee_cat_name": "Certification Fee Year 3"
},
{
"fee_cat_id": "12",
"fee_cat_name": "Certification Fee Year 4"
}
]
}
}
I am using built value in my project
library dashboard_fiscal_year_model;
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'dashboard_fiscal_year_model.g.dart';
abstract class DashboardFiscalYearModel
implements
Built<DashboardFiscalYearModel, DashboardFiscalYearModelBuilder> {
DashboardFiscalYearModel._();
factory DashboardFiscalYearModel(
[updates(DashboardFiscalYearModelBuilder b)]) =
_$DashboardFiscalYearModel;
#BuiltValueField(wireName: 'status')
int get status;
#BuiltValueField(wireName: 'msg')
String get msg;
#BuiltValueField(wireName: 'data')
DashboardFiscalYearData get data;
static Serializer<DashboardFiscalYearModel> get serializer =>
_$dashboardFiscalYearModelSerializer;
}
abstract class DashboardFiscalYearData
implements Built<DashboardFiscalYearData, DashboardFiscalYearDataBuilder> {
DashboardFiscalYearData._();
factory DashboardFiscalYearData([updates(DashboardFiscalYearDataBuilder b)]) =
_$DashboardFiscalYearData;
#BuiltValueField(wireName: 'getFeeCount')
BuiltList<GetFeeCount> get getFeeCount;
#BuiltValueField(wireName: 'getFeeCat')
BuiltList<GetFeeCat> get getFeeCat;
static Serializer<DashboardFiscalYearData> get serializer =>
_$dashboardFiscalYearDataSerializer;
}
abstract class GetFeeCount implements Built<GetFeeCount, GetFeeCountBuilder> {
GetFeeCount._();
factory GetFeeCount([updates(GetFeeCountBuilder b)]) = _$GetFeeCount;
#nullable
#BuiltValueField(wireName: 'yearId')
String get yearId;
#nullable
#BuiltValueField(wireName: 'yearName')
String get yearName;
static Serializer<GetFeeCount> get serializer => _$getFeeCountSerializer;
}
abstract class GetFeeCat implements Built<GetFeeCat, GetFeeCatBuilder> {
GetFeeCat._();
factory GetFeeCat([updates(GetFeeCatBuilder b)]) = _$GetFeeCat;
#nullable
#BuiltValueField(wireName: 'fee_cat_id')
String get feeCatId;
#nullable
#BuiltValueField(wireName: 'fee_cat_name')
String get feeCatName;
}
but whenever I run my app I get the following error
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: Deserializing '[status, 1, msg, Success, data, {getFeeCount: [{yearId: 1, yearName: FY 2017-...' to 'DashboardFiscalYearModel' failed due to: Deserializing '[getFeeCount, [{yearId: 1, yearName: FY 2017-18}, {yearId: 2, yearName: FY 20...' to 'DashboardFiscalYearData' failed due to: Deserializing '[{fee_cat_id: 1, fee_cat_name: 1st Semester Tuition Fee}, {fee_cat_id: 2, fee...' to 'BuiltList<GetFeeCat>' failed due to: Invalid argument(s): Unknown type on deserialization. Need either specifiedType or discriminator field.
#0 BuiltJsonSerializers._deserialize (package:built_value/src/built_json_serializers.dart:154:11)
#1 BuiltJsonSerializers.deserialize (package:built_value/src/built_json_serializers.dart:105:18)
#2 BuiltJsonSerializers.deserializeWith (package:built_value/src/built_json_serializers.dart:35:12)
#3 DashboardDropDownApiProvider.getFiscalYear (package:dice_admin/resources/dashboard/dashboard_fiscal_year/dashboard_fi<…>
[VERBOSE-2:shell.cc(178)] Dart Error: Unhandled exception:
'dart:isolate/runtime/libtimer_impl.dart': Failed assertion: line 433: '<optimized out>': is not true.
#0 _AssertionError._doThrowNew (dart:core/runtime/liberrors_patch.dart:40:39)
#1 _AssertionError._throwNew (dart:core/runtime/liberrors_patch.dart:36:5)
#2 _Timer._cancelWakeup (dart:isolate/runtime/libtimer_impl.dart:433:12)
#3 _Timer._notifyEventHandler (dart:isolate/runtime/libtimer_impl.dart:299:7)
#4 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:419:5)
#5 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
I have regenerated the code many times and the serialiser is also mapped properly I think.
I went through this post https://github.com/google/built_value.dart/issues/368
It uses a custom plugin, has built value resolved this issue or do I need to use the custom built value
I forgot to add Serailizer for GetFeeCat class
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
part 'serializers.g.dart';
// ignore: always_specify_types
#SerializersFor([
NameModel, // Add model to here
])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
List<T> deserializeListOf<T>(
T Function(Map<String, dynamic>) fromMap,
Iterable<dynamic> values,
) =>
values
.map((dynamic v) => fromMap(v as Map<String, dynamic>))
.toList(growable: false);

Resources