Skip to content

Commit 33124db

Browse files
committed
fix(repository): convert array items to json
1 parent 38d3ec7 commit 33124db

File tree

2 files changed

+70
-23
lines changed

2 files changed

+70
-23
lines changed

packages/repository/src/model.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,32 @@ export class ModelDefinition {
137137
}
138138
}
139139

140+
function asJSON(value: any): any {
141+
if (value == null) return value;
142+
if (typeof value.toJSON === 'function') {
143+
return value.toJSON();
144+
}
145+
// Handle arrays
146+
if (Array.isArray(value)) {
147+
return value.map(item => asJSON(item));
148+
}
149+
return value;
150+
}
151+
152+
function asObject(value: any, options?: Options): any {
153+
if (value == null) return value;
154+
if (typeof value.toObject === 'function') {
155+
return value.toObject(options);
156+
}
157+
if (typeof value.toJSON === 'function') {
158+
return value.toJSON();
159+
}
160+
if (Array.isArray(value)) {
161+
return value.map(item => asObject(item, options));
162+
}
163+
return value;
164+
}
165+
140166
/**
141167
* Base class for models
142168
*/
@@ -148,19 +174,15 @@ export abstract class Model {
148174
* Serialize into a plain JSON object
149175
*/
150176
toJSON(): Object {
151-
const json: AnyObject = {};
152177
const def = (<typeof Model>this.constructor).definition;
153178
if (def == null || def.settings.strict === false) {
154179
return this.toObject({ignoreUnknownProperties: false});
155180
}
156181

182+
const json: AnyObject = {};
157183
for (const p in def.properties) {
158184
if (p in this) {
159-
let val = (this as AnyObject)[p];
160-
if (val != null && typeof val.toJSON === 'function') {
161-
val = val.toJSON();
162-
}
163-
json[p] = val;
185+
json[p] = asJSON((this as AnyObject)[p]);
164186
}
165187
}
166188
return json;
@@ -175,13 +197,7 @@ export abstract class Model {
175197
obj = {};
176198
for (const p in this) {
177199
let val = (this as AnyObject)[p];
178-
if (val != null && typeof val.toObject === 'function') {
179-
val = val.toObject(options);
180-
} else if (val != null && typeof val.toJSON === 'function') {
181-
// Fallback to toJSON()
182-
val = val.toJSON();
183-
}
184-
obj[p] = val;
200+
obj[p] = asObject(val, options);
185201
}
186202
} else {
187203
obj = this.toJSON();

packages/repository/test/unit/model/model.unit.ts

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,14 @@ import {STRING} from '../../../';
88
import {Entity, ModelDefinition} from '../../../';
99

1010
describe('model', () => {
11-
const addressDef = new ModelDefinition('Address');
12-
addressDef
13-
.addProperty('street', 'string')
14-
.addProperty('city', 'string')
15-
.addProperty('state', String)
16-
.addProperty('zipCode', STRING);
17-
1811
const customerDef = new ModelDefinition('Customer');
1912
customerDef
2013
.addProperty('id', 'string')
2114
.addProperty('email', 'string')
2215
.addProperty('firstName', String)
2316
.addProperty('lastName', STRING)
2417
.addProperty('address', 'object')
18+
.addProperty('phones', 'array')
2519
.addSetting('id', 'id');
2620

2721
const realmCustomerDef = new ModelDefinition('RealmCustomer');
@@ -44,6 +38,13 @@ describe('model', () => {
4438
.addProperty('id', {type: 'string', id: true})
4539
.addSetting('strict', false);
4640

41+
const addressDef = new ModelDefinition('Address');
42+
addressDef
43+
.addProperty('street', 'string')
44+
.addProperty('city', 'string')
45+
.addProperty('state', String)
46+
.addProperty('zipCode', STRING);
47+
4748
class Address extends Entity {
4849
static definition = addressDef;
4950
street: string;
@@ -56,13 +57,27 @@ describe('model', () => {
5657
}
5758
}
5859

60+
const phoneDef = new ModelDefinition('Phone');
61+
phoneDef.addProperty('number', 'string').addProperty('label', 'string');
62+
63+
class Phone extends Entity {
64+
static definition = phoneDef;
65+
number: string;
66+
label: string;
67+
68+
constructor(data?: Partial<Phone>) {
69+
super(data);
70+
}
71+
}
72+
5973
class Customer extends Entity {
6074
static definition = customerDef;
6175
id: string;
6276
email: string;
6377
firstName: string;
6478
lastName: string;
6579
address?: Address;
80+
phones?: Phone[];
6681

6782
constructor(data?: Partial<Customer>) {
6883
super(data);
@@ -110,7 +125,7 @@ describe('model', () => {
110125
return customer;
111126
}
112127

113-
function createCustomerWithAddress() {
128+
function createCustomerWithContact() {
114129
const customer = new Customer();
115130
customer.id = '123';
116131
customer.email = 'xyz@example.com';
@@ -120,6 +135,10 @@ describe('model', () => {
120135
state: 'CA',
121136
zipCode: '95131',
122137
});
138+
customer.phones = [
139+
new Phone({label: 'home', number: '111-222-3333'}),
140+
new Phone({label: 'work', number: '111-222-5555'}),
141+
];
123142
return customer;
124143
}
125144

@@ -159,7 +178,7 @@ describe('model', () => {
159178
});
160179

161180
it('converts to json recursively', () => {
162-
const customer = createCustomerWithAddress();
181+
const customer = createCustomerWithContact();
163182
expect(customer.toJSON()).to.eql({
164183
id: '123',
165184
email: 'xyz@example.com',
@@ -169,6 +188,10 @@ describe('model', () => {
169188
state: 'CA',
170189
zipCode: '95131',
171190
},
191+
phones: [
192+
{label: 'home', number: '111-222-3333'},
193+
{label: 'work', number: '111-222-5555'},
194+
],
172195
});
173196
});
174197

@@ -191,7 +214,7 @@ describe('model', () => {
191214
});
192215

193216
it('converts to plain object recursively', () => {
194-
const customer = createCustomerWithAddress();
217+
const customer = createCustomerWithContact();
195218
Object.assign(customer, {unknown: 'abc'});
196219
Object.assign(customer.address, {unknown: 'xyz'});
197220
expect(customer.toObject()).to.eql({
@@ -203,6 +226,10 @@ describe('model', () => {
203226
state: 'CA',
204227
zipCode: '95131',
205228
},
229+
phones: [
230+
{label: 'home', number: '111-222-3333'},
231+
{label: 'work', number: '111-222-5555'},
232+
],
206233
});
207234
expect(customer.toObject({ignoreUnknownProperties: false})).to.eql({
208235
id: '123',
@@ -215,6 +242,10 @@ describe('model', () => {
215242
zipCode: '95131',
216243
unknown: 'xyz',
217244
},
245+
phones: [
246+
{label: 'home', number: '111-222-3333'},
247+
{label: 'work', number: '111-222-5555'},
248+
],
218249
});
219250
});
220251

0 commit comments

Comments
 (0)