Skip to content

Commit

Permalink
fix(repository): convert array items to json
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed Sep 14, 2018
1 parent 38d3ec7 commit 33124db
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 23 deletions.
42 changes: 29 additions & 13 deletions packages/repository/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,32 @@ export class ModelDefinition {
}
}

function asJSON(value: any): any {
if (value == null) return value;
if (typeof value.toJSON === 'function') {
return value.toJSON();
}
// Handle arrays
if (Array.isArray(value)) {
return value.map(item => asJSON(item));
}
return value;
}

function asObject(value: any, options?: Options): any {
if (value == null) return value;
if (typeof value.toObject === 'function') {
return value.toObject(options);
}
if (typeof value.toJSON === 'function') {
return value.toJSON();
}
if (Array.isArray(value)) {
return value.map(item => asObject(item, options));
}
return value;
}

/**
* Base class for models
*/
Expand All @@ -148,19 +174,15 @@ export abstract class Model {
* Serialize into a plain JSON object
*/
toJSON(): Object {
const json: AnyObject = {};
const def = (<typeof Model>this.constructor).definition;
if (def == null || def.settings.strict === false) {
return this.toObject({ignoreUnknownProperties: false});
}

const json: AnyObject = {};
for (const p in def.properties) {
if (p in this) {
let val = (this as AnyObject)[p];
if (val != null && typeof val.toJSON === 'function') {
val = val.toJSON();
}
json[p] = val;
json[p] = asJSON((this as AnyObject)[p]);
}
}
return json;
Expand All @@ -175,13 +197,7 @@ export abstract class Model {
obj = {};
for (const p in this) {
let val = (this as AnyObject)[p];
if (val != null && typeof val.toObject === 'function') {
val = val.toObject(options);
} else if (val != null && typeof val.toJSON === 'function') {
// Fallback to toJSON()
val = val.toJSON();
}
obj[p] = val;
obj[p] = asObject(val, options);
}
} else {
obj = this.toJSON();
Expand Down
51 changes: 41 additions & 10 deletions packages/repository/test/unit/model/model.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@ import {STRING} from '../../../';
import {Entity, ModelDefinition} from '../../../';

describe('model', () => {
const addressDef = new ModelDefinition('Address');
addressDef
.addProperty('street', 'string')
.addProperty('city', 'string')
.addProperty('state', String)
.addProperty('zipCode', STRING);

const customerDef = new ModelDefinition('Customer');
customerDef
.addProperty('id', 'string')
.addProperty('email', 'string')
.addProperty('firstName', String)
.addProperty('lastName', STRING)
.addProperty('address', 'object')
.addProperty('phones', 'array')
.addSetting('id', 'id');

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

const addressDef = new ModelDefinition('Address');
addressDef
.addProperty('street', 'string')
.addProperty('city', 'string')
.addProperty('state', String)
.addProperty('zipCode', STRING);

class Address extends Entity {
static definition = addressDef;
street: string;
Expand All @@ -56,13 +57,27 @@ describe('model', () => {
}
}

const phoneDef = new ModelDefinition('Phone');
phoneDef.addProperty('number', 'string').addProperty('label', 'string');

class Phone extends Entity {
static definition = phoneDef;
number: string;
label: string;

constructor(data?: Partial<Phone>) {
super(data);
}
}

class Customer extends Entity {
static definition = customerDef;
id: string;
email: string;
firstName: string;
lastName: string;
address?: Address;
phones?: Phone[];

constructor(data?: Partial<Customer>) {
super(data);
Expand Down Expand Up @@ -110,7 +125,7 @@ describe('model', () => {
return customer;
}

function createCustomerWithAddress() {
function createCustomerWithContact() {
const customer = new Customer();
customer.id = '123';
customer.email = '[email protected]';
Expand All @@ -120,6 +135,10 @@ describe('model', () => {
state: 'CA',
zipCode: '95131',
});
customer.phones = [
new Phone({label: 'home', number: '111-222-3333'}),
new Phone({label: 'work', number: '111-222-5555'}),
];
return customer;
}

Expand Down Expand Up @@ -159,7 +178,7 @@ describe('model', () => {
});

it('converts to json recursively', () => {
const customer = createCustomerWithAddress();
const customer = createCustomerWithContact();
expect(customer.toJSON()).to.eql({
id: '123',
email: '[email protected]',
Expand All @@ -169,6 +188,10 @@ describe('model', () => {
state: 'CA',
zipCode: '95131',
},
phones: [
{label: 'home', number: '111-222-3333'},
{label: 'work', number: '111-222-5555'},
],
});
});

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

it('converts to plain object recursively', () => {
const customer = createCustomerWithAddress();
const customer = createCustomerWithContact();
Object.assign(customer, {unknown: 'abc'});
Object.assign(customer.address, {unknown: 'xyz'});
expect(customer.toObject()).to.eql({
Expand All @@ -203,6 +226,10 @@ describe('model', () => {
state: 'CA',
zipCode: '95131',
},
phones: [
{label: 'home', number: '111-222-3333'},
{label: 'work', number: '111-222-5555'},
],
});
expect(customer.toObject({ignoreUnknownProperties: false})).to.eql({
id: '123',
Expand All @@ -215,6 +242,10 @@ describe('model', () => {
zipCode: '95131',
unknown: 'xyz',
},
phones: [
{label: 'home', number: '111-222-3333'},
{label: 'work', number: '111-222-5555'},
],
});
});

Expand Down

0 comments on commit 33124db

Please sign in to comment.