Skip to content

Commit

Permalink
feat: add support for set and map #181
Browse files Browse the repository at this point in the history
  • Loading branch information
GillianPerard committed Aug 17, 2022
1 parent 861f182 commit 5a5ee26
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 16 deletions.
8 changes: 4 additions & 4 deletions examples/json/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,11 @@ greatZoo.coordinates = {
z: data.zoos[0].coordinates[2]
};
greatZoo.country = data.zoos[0].country;
greatZoo.employees = [bob, mikasa, red, fried];
greatZoo.employees = new Set([bob, mikasa, red, fried]);
greatZoo.id = data.zoos[0].id;
greatZoo.mascot = bagheera;
greatZoo.name = data.zoos[0].name;
greatZoo.unknownAnimals = { '1': unknownAnimal };
greatZoo.unknownAnimals = new Map([['1', unknownAnimal]]);
greatZoo.phoneBook = {
'1': new PhoneNumber(data.zoos[0].phoneBook['1'].value),
'2': new PhoneNumber(data.zoos[0].phoneBook['2'].value),
Expand All @@ -275,11 +275,11 @@ zooZoo.coordinates = {
z: data.zoos[1].coordinates[2]
};
zooZoo.country = data.zoos[1].country;
zooZoo.employees = [];
zooZoo.employees = new Set([]);
zooZoo.id = data.zoos[1].id;
zooZoo.mascot = data.zoos[1].mascot;
zooZoo.name = data.zoos[1].name;
zooZoo.unknownAnimals = {};
zooZoo.unknownAnimals = new Map();

const elonMusk = new Human(
data.mainShareholder.name,
Expand Down
8 changes: 4 additions & 4 deletions examples/models/zoo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JsonProperty, JsonObject } from '../../src';
import { JsonObject, JsonProperty } from '../../src';

import { Animal } from './animal';
import { Employee } from './employee';
Expand Down Expand Up @@ -39,7 +39,7 @@ export class Zoo {
@JsonProperty()
description: string;
@JsonProperty({ type: Employee })
employees: Array<Employee>;
employees: Set<Employee>;
@JsonProperty()
id: number;
@JsonProperty()
Expand All @@ -48,8 +48,8 @@ export class Zoo {
animals: Array<Animal>;
@JsonProperty({ type: snakeOrPanther })
mascot: Panther | Snake;
@JsonProperty({ isDictionary: true, type: UnknownAnimal })
unknownAnimals: { [id: string]: UnknownAnimal };
@JsonProperty({ type: UnknownAnimal })
unknownAnimals: Map<string, UnknownAnimal>;
@JsonProperty({
isDictionary: true,
type: phoneNumberType
Expand Down
49 changes: 41 additions & 8 deletions src/json-serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ export class JsonSerializer {
}

const type = Reflection.getType(instance, propertyKey);
const isArrayProperty = type?.name?.toLowerCase() === 'array';
const typeName = type?.name?.toLowerCase();
const isArrayProperty = typeName === 'array';
const isSetProperty = typeName === 'set';
const isMapProperty = typeName === 'map';
let propertyType = metadata.type || type;

if (metadata.beforeDeserialize) {
Expand All @@ -307,10 +310,18 @@ export class JsonSerializer {
let property: any;
const predicate = metadata.predicate;

if (metadata.isDictionary) {
if (metadata.isDictionary || isMapProperty) {
property = this.deserializeDictionary(dataSource, propertyType, predicate);
} else if (isArrayProperty) {

if (isMapProperty) {
property = new Map(Object.entries(property));
}
} else if (isArrayProperty || isSetProperty) {
property = this.deserializeArray(dataSource, propertyType, predicate);

if (isSetProperty) {
property = new Set(property);
}
} else if (
(!isJsonObject(propertyType) && !predicate) ||
(predicate && !predicate(dataSource, obj))
Expand Down Expand Up @@ -550,18 +561,40 @@ export class JsonSerializer {
private serializeProperty(instance: object, key: string, metadata: JsonPropertyMetadata): any {
const property = instance[key];
const type = Reflection.getType(instance, key);
const isArrayProperty = type?.name?.toLocaleLowerCase() === 'array';
const typeName = type?.name?.toLowerCase();
const isArrayProperty = typeName === 'array';
const isSetProperty = typeName === 'set';
const isMapProperty = typeName === 'map';
const predicate = metadata.predicate;
const propertyType = metadata.type || type;
const isJsonObjectProperty = isJsonObject(propertyType);

if (property && (isJsonObjectProperty || predicate)) {
if (isArrayProperty) {
return this.serializeObjectArray(property);
if (isArrayProperty || isSetProperty) {
const array = isSetProperty ? Array.from(property) : property;
return this.serializeObjectArray(array);
}

if (metadata.isDictionary) {
return this.serializeDictionary(property);
if (metadata.isDictionary || isMapProperty) {
if (!isMapProperty) {
return this.serializeDictionary(property);
}

const obj = {};
property.forEach((value, mapKey) => {
if (isString(mapKey)) {
obj[mapKey] = value;
} else {
this.error(
`Fail to serialize: type of '${typeof mapKey}' is not assignable to type 'string'.\nReceived: ${JSON.stringify(
mapKey
)}.`
);
}
});

console.log(obj);
return this.serializeDictionary(obj);
}

return this.serializeObject(property);
Expand Down

0 comments on commit 5a5ee26

Please sign in to comment.