Loop through JSON Object Swift 5 - ios

I am trying to iterate through a JSON object and obtain specific values in the swift programming language.
I am receiving a JSON like so
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any],
let charges = json["charges"] as? [String:Any]
json:
{
object: 'list',
data: [
{
id: 'ch_1IWQEfKn7R1M6tqnhrpyIhMk',
object: 'charge',
amount: 555,
amount_captured: 555,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IWQEfKn7R1M6tqnvTHQeSEF',
application_fee_amount: 6,
balance_transaction: 'txn_1IWQEfKn7R1M6tqnkK9LCNuM',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1616090777,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IWQEeKn7R1M6tqnYbGfFCzg',
payment_method: 'pm_1IWQEeKn7R1M6tqnKLxSg6vZ',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IWQEfKn7R1M6tqnhrpyIhMk/rcpt_J8hdy05N6VfOmRECdumpti8Jiljz2Et',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
},
{
id: 'ch_1IU62QKn7R1M6tqnbXXlOpch',
object: 'charge',
amount: 5599,
amount_captured: 5599,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IU62RKn7R1M6tqnLle3zblA',
application_fee_amount: 56,
balance_transaction: 'txn_1IU62RKn7R1M6tqn3ttu9F3N',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1615536482,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IU62NKn7R1M6tqnWSOLJVge',
payment_method: 'pm_1IU62PKn7R1M6tqnIyOUgUMX',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IU62QKn7R1M6tqnbXXlOpch/rcpt_J6Id30gjIhQU6AWPBHgUXoujbhFOTyf',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
},
{
id: 'ch_1IU60cKn7R1M6tqny9o2NV5W',
object: 'charge',
amount: 1000,
amount_captured: 1000,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IU60cKn7R1M6tqn95nUHETe',
application_fee_amount: 10,
balance_transaction: 'txn_1IU60cKn7R1M6tqnZKNbSEXf',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1615536370,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IU60ZKn7R1M6tqnrUSK1TQD',
payment_method: 'pm_1IU60bKn7R1M6tqnAUHQXqJG',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IU60cKn7R1M6tqny9o2NV5W/rcpt_J6Ib5PEZQzEgyXWoOwKcxZ9x7mByCVu',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
}
],
has_more: true,
url: '/v1/charges'
}
How can I iterate through the JSON object to receive "amount", "currency", and "id".
For example PSUEDO:
for item in charges {
print(item["amount"])
print(item["currency"])
print(item["id"])
}
I may be initializing the json improperly such as
json["charges"] as? [String:Any]

You shouldn't use try ? - This throws away errors. Always use do/try/catch so that you handle any errors that occur, even if you just print them.
JSONSerialization and decoding JSON to arrays and dictionaries isn't best practice. It is much better to create suitable structs that conform to Codable and use JSONDecoder.
struct Response: Codable {
var object: String
var hasMore: Bool
var data: [ResponseData]
var url: String
enum CodingKeys: String, CodingKey {
case object
case hasMore = "has_more"
case url
case data
}
}
struct ResponseData: Codable {
var amount: Int
var currency: String
var id: String
}
For simplicity I have't added all of the properties to the ResponseData struct, just the ones you have said you are interested in
do {
let json = try JSONDecoder().decode(Response.self, from: data)
json.data.forEach { charge in
print(charge.id)
print(charge.currency)
print(charge.ammount)
}
} catch {
print("Error! \(error)")
}

Related

toJson method throws stackOverflow

from backend I'm receiving json that looks like this
{
"teamDto": {
"id": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"teamName": "tasdasd",
"payPerPractice": 123.0,
"payPerGame": 123.0,
"season": "asdasd",
"teamMembers": [
{
"id": "4657dd50-974c-427c-8e77-0f5e1f4fd23c",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "6a758edd-fbac-49b5-bed4-250c585b5c3f",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "98786a8a-3915-4e3a-b832-32fc6c4d8b8d",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "c3e76455-a7bb-4be4-abe7-09436f6fe3df",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
}
],
"sport": null
},
"owner": true,
"manager": true
}
I'm aware of imperfections in my json, but thats not the problem.
The problem is when i try to convert it to object, my programm throws stackoverflow.
Here is my TeamDashboardDtoclass
class TeamDashboardDto{
late TeamDto teamDto;
late bool isOwner;
late bool isManager;
TeamDashboardDto({required this.teamDto, required this.isOwner, required this.isManager});
factory TeamDashboardDto.fromJson(Map<String, dynamic> json) => TeamDashboardDto.fromJson(json);
Map<String, dynamic> toJson() => UserAndTeamDtoToJson(this);
Map<String, dynamic> UserAndTeamDtoToJson(TeamDashboardDto instance) => <String, dynamic>{
'teamDto': instance.teamDto,
'owner': instance.isOwner,
'manager': instance.isManager,
};
}
and here is my TeamDto class
class TeamDto{
String? id;
String? teamName;
double? payPerPractice;
double? payPerGame;
String? season;
List<TeamMemberDto>? teamMembers;
TeamDto({this.id, this.teamName, this.payPerGame, this.payPerPractice, this.season, this.teamMembers});
factory TeamDto.fromJson(Map<String, dynamic> json) {
return TeamDto(
id: json['id'],
teamName: json['teamName'],
payPerPractice: json['payPerPractice'],
payPerGame: json['payPerGame'],
season: json['season'],
teamMembers: List<TeamMemberDto>.from(
json['teamMembers'].map((model) => TeamMemberDto.fromJson(model)))
);
}
Map<String, dynamic> toJson() => {
'id': id,
'teamName': teamName,
'sport': sport,
'payPerGame': payPerGame,
"payPerPractice": payPerPractice,
"season": season,
"teamMembers": teamMembers
};
}
I dont see why theres a problem because i have other Dto classes that contain two different dto's which one of them is TeamDto, the only difference here is that this dto class contains two booleans and another dto class instead of two dto classes.
You have an infinite call loop here:
factory TeamDashboardDto.fromJson(Map<String, dynamic> json)
=> TeamDashboardDto.fromJson(json);
So your TeamDashboardDto.fromJson factory are calling the TeamDashboardDto.fromJson factory which are calling the TeamDashboardDto.fromJson factory... and so on since it is just calling itself.
This code was generated by other small script.
Generation script was written in less than 5 minutes.
import 'dart:convert';
void main() {
final json = jsonDecode(_response) as Map;
final response = Response.fromJson(json);
print(response.teamDto.teamMembers[0].id);
}
const _response = '''
{
"teamDto": {
"id": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"teamName": "tasdasd",
"payPerPractice": 123.0,
"payPerGame": 123.0,
"season": "asdasd",
"teamMembers": [
{
"id": "4657dd50-974c-427c-8e77-0f5e1f4fd23c",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "6a758edd-fbac-49b5-bed4-250c585b5c3f",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "98786a8a-3915-4e3a-b832-32fc6c4d8b8d",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "c3e76455-a7bb-4be4-abe7-09436f6fe3df",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
}
],
"sport": null
},
"owner": true,
"manager": true
}''';
class Response {
Response({required this.teamDto, required this.owner, required this.manager});
factory Response.fromJson(Map json) {
return Response(
teamDto: TeamDto.fromJson(json['teamDto'] as Map),
owner: json['owner'] == null ? false : json['owner'] as bool,
manager: json['manager'] == null ? false : json['manager'] as bool,
);
}
final TeamDto teamDto;
final bool owner;
final bool manager;
static List<Response> fromJsonList(List json) {
return json.map((e) => Response.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'teamDto': teamDto.toJson(),
'owner': owner,
'manager': manager,
};
}
static List<Map<String, dynamic>> toJsonList(List<Response> list) {
return list.map((e) => e.toJson()).toList();
}
}
class TeamDto {
TeamDto(
{required this.id,
required this.teamName,
required this.payPerPractice,
required this.payPerGame,
required this.season,
required this.teamMembers,
required this.sport});
factory TeamDto.fromJson(Map json) {
return TeamDto(
id: json['id'] == null ? '' : json['id'] as String,
teamName: json['teamName'] == null ? '' : json['teamName'] as String,
payPerPractice: json['payPerPractice'] == null
? 0.0
: json['payPerPractice'] as double,
payPerGame:
json['payPerGame'] == null ? 0.0 : json['payPerGame'] as double,
season: json['season'] == null ? '' : json['season'] as String,
teamMembers: json['teamMembers'] == null
? []
: (json['teamMembers'] as List)
.map((e) => TeamMemberDto.fromJson(e as Map))
.toList(),
sport: json['sport'],
);
}
final String id;
final String teamName;
final double payPerPractice;
final double payPerGame;
final String season;
final List<TeamMemberDto> teamMembers;
final Object? sport;
static List<TeamDto> fromJsonList(List json) {
return json.map((e) => TeamDto.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'teamName': teamName,
'payPerPractice': payPerPractice,
'payPerGame': payPerGame,
'season': season,
'teamMembers': teamMembers.map((e) => e.toJson()).toList(),
'sport': sport,
};
}
static List<Map<String, dynamic>> toJsonList(List<TeamDto> list) {
return list.map((e) => e.toJson()).toList();
}
}
class TeamMemberDto {
TeamMemberDto(
{required this.id,
required this.isOwner,
required this.isManager,
required this.teamName,
required this.teamId,
required this.name,
required this.lastName});
factory TeamMemberDto.fromJson(Map json) {
return TeamMemberDto(
id: json['id'] == null ? '' : json['id'] as String,
isOwner: json['isOwner'] == null ? false : json['isOwner'] as bool,
isManager: json['isManager'] == null ? false : json['isManager'] as bool,
teamName: json['teamName'] == null ? '' : json['teamName'] as String,
teamId: json['teamId'] == null ? '' : json['teamId'] as String,
name: json['name'] as String?,
lastName: json['lastName'] as String?,
);
}
final String id;
final bool isOwner;
final bool isManager;
final String teamName;
final String teamId;
final String? name;
final String? lastName;
static List<TeamMemberDto> fromJsonList(List json) {
return json.map((e) => TeamMemberDto.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'isOwner': isOwner,
'isManager': isManager,
'teamName': teamName,
'teamId': teamId,
'name': name,
'lastName': lastName,
};
}
static List<Map<String, dynamic>> toJsonList(List<TeamMemberDto> list) {
return list.map((e) => e.toJson()).toList();
}
}
Generation script.
Models defined in simple YAML format.
It also includes an example template that can be easily removed.
import 'dart:io';
import 'package:object_serializer/json_serializer_generator.dart';
import 'package:yaml/yaml.dart';
void main() {
final classes = loadYaml(_classes) as Map;
final g = JsonSerializerGenerator();
final classesCode = g.generateClasses(classes);
final values = {
'classes': classesCode,
};
var source = g.render(_template, values);
source = g.format(source);
File('bin/stackoverflow.dart').writeAsStringSync(source);
}
const _classes = r'''
Response:
fields:
teamDto: TeamDto
owner: bool
manager: bool
TeamDto:
fields:
id: String
teamName: String
payPerPractice: double
payPerGame: double
season: String
teamMembers: List<TeamMemberDto>
sport: Object?
TeamMemberDto:
fields:
id: String
isOwner: bool
isManager: bool
teamName: String
teamId: String
name: String?
lastName: String?
''';
const _template = r"""
import 'dart:convert';
void main() {
final json = jsonDecode(_response) as Map;
final response = Response.fromJson(json);
print(response.teamDto.teamMembers[0].id);
}
const _response =
'''
{
"teamDto": {
"id": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"teamName": "tasdasd",
"payPerPractice": 123.0,
"payPerGame": 123.0,
"season": "asdasd",
"teamMembers": [
{
"id": "4657dd50-974c-427c-8e77-0f5e1f4fd23c",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "6a758edd-fbac-49b5-bed4-250c585b5c3f",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "98786a8a-3915-4e3a-b832-32fc6c4d8b8d",
"isOwner": true,
"isManager": true,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
},
{
"id": "c3e76455-a7bb-4be4-abe7-09436f6fe3df",
"isOwner": false,
"isManager": false,
"teamName": "tasdasd",
"teamId": "34ec8e71-b5a9-4a4c-b461-5cbb562329b5",
"name": null,
"lastName": null
}
],
"sport": null
},
"owner": true,
"manager": true
}''';
{{classes}}
""";

How to add multiple examples to a Swagger schema?

I'm using Swagger with OAS3, since I need anyOf support. I have an API call that can take one of 2 possible schemas, an account or an address. The schema works well in Swagger: it shows, and validates. But the example value shows only the first schema. I created an examples array, per the documentation, but I have no idea where to add it:
const accountSchema = {
description: 'schema for adding a new account',
type: 'object',
properties: {
account: {
type: 'object',
properties: {
userId: {type: 'number'},
platformId: {type: 'number'},
name: {type: 'string'},
key: {type: 'string'},
secret: {type: 'string'},
test: {type: 'boolean'},
},
required: ['userId', 'platformId', 'name', 'key', 'secret']
}
},
};
const ethereumAddressSchema = {
description: 'schema for adding a new ethereum address',
type: 'object',
properties: {
ethereum: {
type: 'object',
properties: {
userId: {type: 'number'},
name: {type: 'string'},
address: {type: 'string'},
chainId: {type: 'number'},
},
required: ['userId','name', 'address']
}
}
};
const examples = [
{
account: {
"userId": 0,
"platformId": 0,
"name": "string",
"key": "string",
"secret": "string",
"test": true
},
},
{
ethereum: {
"userId": 0,
"address": '0xfffffffffffffff',
"name": "string",
"chainId": 1,
}
}
];
const body = {
anyOf: [accountSchema, ethereumAddressSchema]
};
const response = {
type: 'object',
properties: {
accountId: {type: 'number'},
reason: {type: 'string'}
},
required: []
};
const addAccountSchema = {
description: 'Add a new account',
tags: ['account'],
produces: ['application/json'],
summary: 'Add a new account',
body,
response: {
200: {
description: 'Account request valid',
...response
},
404: {
description: 'Account request parameters not found',
...response
},
422: {
description: 'Account request invalid',
...response
}
}
};
module.exports = addAccountSchema;
Where should I add the examples array, or is there a better way to show the user the 2 possible schemas in the UI?

Navigating jbuilder to attatch html string

I am setting up a collection of ruby issues (#issues) into arrays using jbuilder so they plug into datatables. Normally with datatables each row represents a single record and you determine the columns by their fields (:id, :name, etc)
In this case each issue has a status (:initial, waiting_on_customer, waiting_on_user, waiting_on_supplier, closed) and is sorted in the controller so the #issues object looks like this where each "row" is comprised of 5 issues, one for each status
{
initial: {
id: 3,
priority: "Low",
status: "initial",
name: "Broken Parts",
notes: "shaft was bent",
created_at: "2020-11-20T00:45:40.000Z",
updated_at: "2020-11-23T15:39:59.000Z",
purchase_order_id: null,
deleted_at: null,
tenant_id: null,
supplier_id: null,
incoming_order_id: null
},
waiting_on_user: {
id: 8,
priority: "Medium",
status: "waiting_on_user",
name: "Poor Communication",
notes: "Supplier wont return call",
created_at: "2020-11-20T05:56:49.000Z",
updated_at: "2020-11-23T22:39:25.000Z",
purchase_order_id: null,
deleted_at: null,
tenant_id: null,
supplier_id: 2,
incoming_order_id: null
},
waiting_on_supplier: {
id: 4,
priority: "Low",
status: "waiting_on_supplier",
name: "Payment reversed",
notes: "Check bounced",
created_at: "2020-11-20T00:46:02.000Z",
updated_at: "2020-11-23T22:39:31.000Z",
purchase_order_id: null,
deleted_at: null,
tenant_id: null,
supplier_id: null,
incoming_order_id: null
},
waiting_on_customer: {
id: 1,
priority: "Medium",
status: "waiting_on_customer",
name: "Big Problem",
notes: "Mayday were going down!!",
created_at: "2020-11-20T00:44:34.000Z",
updated_at: "2020-11-23T15:42:52.000Z",
purchase_order_id: null,
deleted_at: null,
tenant_id: null,
supplier_id: null,
incoming_order_id: null
},
closed: {
id: 2,
priority: "High",
status: "closed",
name: "Lost Package",
notes: "Missing package, shipper says it was delivered",
created_at: "2020-11-20T00:45:16.000Z",
updated_at: "2020-11-23T15:39:01.000Z",
purchase_order_id: null,
deleted_at: null,
tenant_id: null,
supplier_id: null,
incoming_order_id: null
}
},
#issues gets passed to index.json.jbuilder
json.array! #issues, partial: "issues/issue", as: :issue_hash
which passes each issue_hash to the issue.json.jbuilder
json.extract! issue_hash, :initial, :waiting_on_user, :waiting_on_supplier, :waiting_on_customer, :closed
I can add the string to the base level of the issue_hash with
json.issue_card_html render 'issue_card_datatable.html.erb',i: issue
But I am trying to attach this html string to the "initial" issue object like so
# json.initial.issue_card_html render 'issue_card_datatable.html.erb',i: issue
but It gets me a no method error for issue_card_html
Ive tried every combination of looping and diving into the json objects I can think of and that are on the jbuilder docs to no avail. I think I must be missing something obvious as it shouldn't be this hard to navigate and manipulate a json object

TypeORM does not save relations

I have the following entity which I want to save:
#Entity('approvals')
export class Approval {
#PrimaryGeneratedColumn()
id: string;
#ManyToOne(type => Task, task => task.approvals, {nullable: false, onDelete: 'CASCADE', lazy: true})
task: Promise<Task> | Task;
#ManyToOne(type => User, user => user.approvals, {nullable: false, onDelete: 'CASCADE', lazy: true})
user: Promise<User> | User;
#Column({ type: 'enum', enum: ApprovalState, default: ApprovalState.None })
state: ApprovalState;
constructor(partialApproval: Partial<Approval>) {
Object.assign(this, partialApproval);
}
}
If I want to save an entity which looks like (copied while debugging):
[
{
"task": {
"id": "2",
"name": "task1",
"type": "type1",
"neededTimeSeconds": 0,
"factor": 1,
"userId": "1",
"periodStart": "2019-01-01",
"periodEnd": "2019-01-31",
"done": true,
"__user__": {
"id": "1",
"username": "user1",
"password": "$2b$10$SBPIVm9p8L4YkpiUVJ.mpedIgWi5Je6MuWTM7IvgMdyhr27JYM0OG",
"credits": 0,
"gravatarHash": null
},
"__has_user__": true
},
"user": {
"id": "2",
"username": "shouldHaveApprovalUser1",
"password": "password1",
"credits": 0,
"gravatarHash": null
}
},
{
"task": {
"id": "2",
"name": "task1",
"type": "type1",
"neededTimeSeconds": 0,
"factor": 1,
"userId": "1",
"periodStart": "2019-01-01",
"periodEnd": "2019-01-31",
"done": true,
"__user__": {
"id": "1",
"username": "user1",
"password": "$2b$10$SBPIVm9p8L4YkpiUVJ.mpedIgWi5Je6MuWTM7IvgMdyhr27JYM0OG",
"credits": 0,
"gravatarHash": null
},
"__has_user__": true
},
"user": {
"id": "3",
"username": "shouldHaveApprovalUser2",
"password": "password1",
"credits": 0,
"gravatarHash": null
}
}
]
Then calling repository.save() with the above array, I get:
null value in column "taskId" violates not-null constraint
Although there is clearly the id defined in each task.
This is the Task entity class:
#Entity('tasks')
export class Task {
#PrimaryGeneratedColumn({ type: 'bigint' })
id: string;
#Column({ length: 30 })
name: string;
#Column({ default: 'help' })
type: string;
#Column({ name: 'needed_time', type: 'int', nullable: true })
neededTimeSeconds: number;
#Column({ type: 'int', default: 1 })
factor: number;
#ManyToOne(type => User, { nullable: true, lazy: true })
#JoinColumn({ name: 'user_id' })
user: Promise<User>;
#Column({ name: 'user_id' })
#RelationId((task: Task) => task.user)
userId: string;
#Column({ name: 'period_start', type: 'date', default: new Date() })
periodStart: string;
#Column({ name: 'period_end', type: 'date', default: new Date() })
periodEnd: string;
#Column({ type: 'boolean', default: false })
done: boolean;
#OneToMany(type => Approval, approval => approval.task, { nullable: true, lazy: true })
approvals: Promise<Approval[]>;
#OneToMany(type => TaskMessage, taskMessage => taskMessage.task, { cascade: ['remove'], lazy: true })
messages: Promise<TaskMessage[]>;
constructor(partialTask: Partial<Task>) {
Object.assign(this, partialTask);
}
}
Can anyone tell me why the relation task is not going to be assigned/saved?
I think you are missing cascade: true for the options of the relations, this should be set on the loose side of the relation (OneToMany) - check the example
You can use Typeorm's cascades for this: https://orkhan.gitbook.io/typeorm/docs/relations#cascades
Setting the cascade property in your relationship decorator changes the behavior of typeorm's .save() method.
#OneToMany(type => Approval, approval => approval.task, {
nullable: true,
lazy: true,
cascade: ["insert", "update", "remove"]
})
approvals: Approval[];
With cascades enabled, you can insert, update or remove related entities with a single call to .save().
To create a new approval and insert task:
await this.approvalsEntity.save({ ...approvalData, task: taskData })
To update a task on a pre-existing approval:
await this.approvalsEntity.save({
id: approvalId,
task: { id: taskId, ...approvalUpdate }
})

Extjs Grid Paging Toolbar Shows All Data and No Page Number

I am using extjs paging toolbar on my grid. I have pagesize 5, but it shows all data(default is I guess 25)... but when I click next page, it still shows the first 25 data. and also have issue with page number where it's blank of 2...when it's suppose to say 1 of 2... Click here to see what it looks like
this is my grid...
var myPageSize = 5;
store.load({
params: {
start: 0,
limit: myPageSize
}
});
this.grid = Ext.create('Ext.grid.Panel', {
title: 'GridView App',
store: store,
loadMask: true,
columns: [{
header: 'Q1',
sortable: true,
dataIndex: 'Q1',
flex: 1,
}, {
header: 'Q2',
sortable: true,
dataIndex: 'Q2',
flex: 1,
}, {
header: 'Q3',
sortable: true,
dataIndex: 'Q3',
flex: 1,
}, {
header: 'Q4',
sortable: true,
dataIndex: 'Q4',
flex: 1,
}, {
header: 'Improvements',
flex: 1,
sortable: true,
dataIndex: 'Improvements'
}, {
header: 'Comments',
flex: 1,
sortable: true,
dataIndex: 'Comments'
}],
bbar: Ext.create('Ext.PagingToolbar', {
style: 'border:1px solid #99BBE8;',
store: store,
displayInfo: true,
preprendButtons: true,
displayMsg: 'Displaying Surveys {0} - {1} of {2}',
emptyMsg: "No Surveys to display"
}),
stripeRows: true,
trackover: true,
renderTo: Ext.getBody()
});
and this is my store
var store = Ext.create('Ext.data.JsonStore', {
storeId: 'myData',
scope: this,
fields: [{
name: 'Q1',
type: 'int'
}, {
name: 'Q2',
type: 'int'
}, {
name: 'Q3',
type: 'int'
}, {
name: 'Q4',
type: 'int'
}, {
name: 'Q5',
type: 'int'
}, {
name: 'Improvements',
type: 'string'
}, {
name: 'Comments',
type: 'string'
}],
sorters: [{
property: 'Q1',
direct: 'ASC'
}],
proxy: {
type: 'ajax',
url: 'GridView/writeRecord',
reader: new Ext.data.JsonReader({
root: 'myTable',
totalProperty: 'count'
})
}
});
And my Json looks like this, please click here
UPDATE JSON RESULT
{
"count": 30,
"myTable": [
{
"Q1": "1",
"Q2": "1",
"Q3": "1",
"Q4": "1",
"Improvements": "",
"Comments": "1"
},
{
"Q1": "1",
"Q2": "2",
"Q3": "3",
"Q4": "4",
"Improvements": "Iphone5",
"Comments": "Iphone14"
},
{
"Q1": "1",
"Q2": "1",
"Q3": "3",
"Q4": "3",
"Improvements": "This is Comment1-3",
"Comments": "This is Comment2-3"
},
The issue is with the data you're returning from server. With that store configuration you must return a json formatted like this (note that records fields are different that yours)
{
"success" : true,
"count" : 2,
"myTable" :[{
"id" : 1,
"cod" :"100001"
},{
"id" : 2,
"cod" :"100001"
}]
}
Store's root parameter is where extjs expects to have the array of records, success parameter is something you can handle to display server comunication errors and totalProperty is where you tell to extjs how many total records you have fetched. (Answer based on extjs 4.x, but as i can remember with 3.x is the same)

Resources