Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: process null values #1248

Merged
merged 17 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions packages/abstractions/src/serialization/parseNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,58 +20,58 @@ export interface ParseNode {
* Gets the string value of the node.
* @return the string value of the node.
*/
getStringValue(): string | undefined;
getStringValue(): string | null | undefined;
baywet marked this conversation as resolved.
Show resolved Hide resolved
/**
* Gets a new parse node for the given identifier.
* @param identifier the identifier of the current node property.
* @return a new parse node for the given identifier.
*/
getChildNode(identifier: string): ParseNode | undefined;
getChildNode(identifier: string): ParseNode | null | undefined;
/**
* Gets the boolean value of the node.
* @return the boolean value of the node.
*/
getBooleanValue(): boolean | undefined;
getBooleanValue(): boolean | null | undefined;
/**
* Gets the Number value of the node.
* @return the Number value of the node.
*/
getNumberValue(): number | undefined;
getNumberValue(): number | null | undefined;
baywet marked this conversation as resolved.
Show resolved Hide resolved
/**
* Gets the Guid value of the node.
* @return the Guid value of the node.
*/
getGuidValue(): Guid | undefined;
getGuidValue(): Guid | null | undefined;
/**
* Gets the Date value of the node.
* @return the Date value of the node.
*/
getDateValue(): Date | undefined;
getDateValue(): Date | null | undefined;
/**
* Gets the Duration value of the node.
* @return the Duration value of the node.
*/
getDurationValue(): Duration | undefined;
getDurationValue(): Duration | null | undefined;
/**
* Gets the DateOnly value of the node.
* @return the DateOnly value of the node.
*/
getDateOnlyValue(): DateOnly | undefined;
getDateOnlyValue(): DateOnly | null | undefined;
/**
* Gets the TimeOnly value of the node.
* @return the TimeOnly value of the node.
*/
getTimeOnlyValue(): TimeOnly | undefined;
getTimeOnlyValue(): TimeOnly | null | undefined;
/**
* Gets the collection of primitive values of the node.
* @return the collection of primitive values of the node.
*/
getCollectionOfPrimitiveValues<T>(): T[] | undefined;
getCollectionOfPrimitiveValues<T>(): T[] | null | undefined;
/**
* Gets the collection of object values of the node.
* @return the collection of object values of the node.
*/
getCollectionOfObjectValues<T extends Parsable>(parsableFactory: ParsableFactory<T>): T[] | undefined;
getCollectionOfObjectValues<T extends Parsable>(parsableFactory: ParsableFactory<T>): T[] | null | undefined;
baywet marked this conversation as resolved.
Show resolved Hide resolved

/**
* Gets the model object value of the node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import type { Parsable } from "./parsable";
import type { ParseNode } from "./parseNode";
import type { SerializationWriter } from "./serializationWriter";

export type ModelSerializerFunction<T extends Parsable> = (writer: SerializationWriter, value?: Partial<T> | undefined) => void;
export type ModelSerializerFunction<T extends Parsable> = (writer: SerializationWriter, value?: Partial<T> | null | undefined) => void;

export type DeserializeIntoModelFunction<T extends Parsable> = (value?: Partial<T> | undefined) => Record<string, (node: ParseNode) => void>;
export type DeserializeIntoModelFunction<T extends Parsable> = (value?: Partial<T> | null | undefined) => Record<string, (node: ParseNode) => void>;
22 changes: 11 additions & 11 deletions packages/abstractions/src/serialization/serializationWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,55 +25,55 @@ export interface SerializationWriter {
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeStringValue(key?: string | undefined, value?: string | undefined): void;
writeStringValue(key?: string | undefined, value?: string | null | undefined): void;
baywet marked this conversation as resolved.
Show resolved Hide resolved
/**
* Writes the specified boolean value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeBooleanValue(key?: string | undefined, value?: boolean | undefined): void;
writeBooleanValue(key?: string | undefined, value?: boolean | null | undefined): void;
/**
* Writes the specified number value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeNumberValue(key?: string | undefined, value?: number | undefined): void;
writeNumberValue(key?: string | undefined, value?: number | null | undefined): void;
/**
* Writes the specified Guid value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeGuidValue(key?: string | undefined, value?: Guid | undefined): void;
writeGuidValue(key?: string | undefined, value?: Guid | null | undefined): void;
/**
* Writes the specified Date value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeDateValue(key?: string | undefined, value?: Date | undefined): void;
writeDateValue(key?: string | undefined, value?: Date | null | undefined): void;
/**
* Writes the specified Duration value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeDurationValue(key?: string | undefined, value?: Duration | undefined): void;
writeDurationValue(key?: string | undefined, value?: Duration | null | undefined): void;
/**
* Writes the specified TimeOnly value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeTimeOnlyValue(key?: string | undefined, value?: TimeOnly | undefined): void;
writeTimeOnlyValue(key?: string | undefined, value?: TimeOnly | null | undefined): void;
/**
* Writes the specified DateOnly value to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeDateOnlyValue(key?: string | undefined, value?: DateOnly | undefined): void;
writeDateOnlyValue(key?: string | undefined, value?: DateOnly | null | undefined): void;
/**
* Writes the specified collection of primitive values to the stream with an optional given key.
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeCollectionOfPrimitiveValues<T>(key?: string | undefined, values?: T[] | undefined): void;
writeCollectionOfPrimitiveValues<T>(key?: string | undefined, values?: T[] | null | undefined): void;
/**
* Writes the specified collection of object values to the stream with an optional given key.
* @param key the key to write the value with.
Expand All @@ -85,14 +85,14 @@ export interface SerializationWriter {
* @param key the key to write the value with.
* @param value the value to write to the stream.
*/
writeObjectValue<T extends Parsable>(key?: string | undefined, value?: T | undefined, serializerMethod?: ModelSerializerFunction<T>): void;
writeObjectValue<T extends Parsable>(key?: string | undefined, value?: T | null | undefined, serializerMethod?: ModelSerializerFunction<T>): void;

/**
* Writes the specified enum value to the stream with an optional given key.
* @param key the key to write the value with.
* @param values the value to write to the stream.
*/
writeEnumValue<T>(key?: string | undefined, ...values: (T | undefined)[]): void;
writeEnumValue<T>(key?: string | undefined, ...values: (T | null | undefined)[]): void;
/**
* Writes a null value for the specified key.
* @param key the key to write the value with.
Expand Down
30 changes: 20 additions & 10 deletions packages/serialization/json/src/jsonParseNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ export class JsonParseNode implements ParseNode {
constructor(private readonly _jsonNode: unknown) {}
public onBeforeAssignFieldValues: ((value: Parsable) => void) | undefined;
public onAfterAssignFieldValues: ((value: Parsable) => void) | undefined;
baywet marked this conversation as resolved.
Show resolved Hide resolved
public getStringValue = () => (typeof this._jsonNode === "string" ? (this._jsonNode as string) : undefined);
public getChildNode = (identifier: string): ParseNode | undefined => (this._jsonNode && typeof this._jsonNode === "object" && (this._jsonNode as { [key: string]: any })[identifier] !== undefined ? new JsonParseNode((this._jsonNode as { [key: string]: any })[identifier]) : undefined);
public getBooleanValue = () => (typeof this._jsonNode === "boolean" ? (this._jsonNode as boolean) : undefined);
public getNumberValue = () => (typeof this._jsonNode === "number" ? (this._jsonNode as number) : undefined);
public getGuidValue = () => parseGuidString(this.getStringValue());
public getDateValue = () => (this._jsonNode ? new Date(this._jsonNode as string) : undefined);
public getDateOnlyValue = () => DateOnly.parse(this.getStringValue());
public getTimeOnlyValue = () => TimeOnly.parse(this.getStringValue());
public getDurationValue = () => Duration.parse(this.getStringValue());
public getStringValue = () => (typeof this._jsonNode === "string" || this._jsonNode === null ? this._jsonNode : undefined);
baywet marked this conversation as resolved.
Show resolved Hide resolved
public getChildNode = (identifier: string): ParseNode | undefined => (this._jsonNode === null ? null : this._jsonNode && typeof this._jsonNode === "object" && (this._jsonNode as { [key: string]: any })[identifier] === null ? null : (this._jsonNode as { [key: string]: any })[identifier] ?? undefined);
public getBooleanValue = () => (typeof this._jsonNode === "boolean" || this._jsonNode === null ? this._jsonNode : undefined);
public getNumberValue = () => (typeof this._jsonNode === "number" || this._jsonNode === null ? this._jsonNode : undefined);
public getGuidValue = () => (this.getStringValue() === null ? null : parseGuidString(this.getStringValue()));
public getDateValue = () => {
if (this._jsonNode === null) {
return null;
}

return this._jsonNode ? new Date(this._jsonNode as string) : undefined;
};
public getDateOnlyValue = () => (this.getStringValue() === null ? null : DateOnly.parse(this.getStringValue()));
public getTimeOnlyValue = () => (this.getStringValue() === null ? null : TimeOnly.parse(this.getStringValue()));
public getDurationValue = () => (this.getStringValue() === null ? null : Duration.parse(this.getStringValue()));
Kindest13 marked this conversation as resolved.
Show resolved Hide resolved
public getCollectionOfPrimitiveValues = <T>(): T[] | undefined => {
if (!Array.isArray(this._jsonNode)) {
return undefined;
Expand Down Expand Up @@ -53,7 +59,11 @@ export class JsonParseNode implements ParseNode {
}
return undefined;
}
public getCollectionOfObjectValues = <T extends Parsable>(method: ParsableFactory<T>): T[] | undefined => {
public getCollectionOfObjectValues = <T extends Parsable>(method: ParsableFactory<T>): T[] | null | undefined => {
if (this._jsonNode === null) {
return null;
Kindest13 marked this conversation as resolved.
Show resolved Hide resolved
}

if (!Array.isArray(this._jsonNode)) {
return undefined;
}
Expand Down
82 changes: 61 additions & 21 deletions packages/serialization/json/src/jsonSerializationWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,82 @@ export class JsonSerializationWriter implements SerializationWriter {
public onBeforeObjectSerialization: ((value: Parsable) => void) | undefined;
public onAfterObjectSerialization: ((value: Parsable) => void) | undefined;
public onStartObjectSerialization: ((value: Parsable, writer: SerializationWriter) => void) | undefined;
public writeStringValue = (key?: string, value?: string): void => {
if (value !== null && value !== undefined) {
key && this.writePropertyName(key);
this.writer.push(JSON.stringify(value));
key && this.writer.push(JsonSerializationWriter.propertySeparator);
public writeStringValue = (key?: string, value?: string | null): void => {
if (value === undefined) {
return;
}

if (value === null) {
key && this.writeNullValue(key);

return;
}

key && this.writePropertyName(key);
this.writer.push(JSON.stringify(value));
key && this.writer.push(JsonSerializationWriter.propertySeparator);
};
private writePropertyName = (key: string): void => {
this.writer.push(`"${key}":`);
};
public writeBooleanValue = (key?: string, value?: boolean): void => {
if (value !== null && value !== undefined) {
key && this.writePropertyName(key);
this.writer.push(`${value}`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
public writeBooleanValue = (key?: string, value?: boolean | null): void => {
if (value === undefined) {
return;
}

if (value === null) {
key && this.writeNullValue(key);

return;
}

key && this.writePropertyName(key);
this.writer.push(`${value}`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
};
public writeNumberValue = (key?: string, value?: number): void => {
if (value !== null && value !== undefined) {
key && this.writePropertyName(key);
this.writer.push(`${value}`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
public writeNumberValue = (key?: string, value?: number | null): void => {
if (value === undefined) {
return;
}

if (value === null) {
key && this.writeNullValue(key);

return;
}

key && this.writePropertyName(key);
this.writer.push(`${value}`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
};
public writeGuidValue = (key?: string, value?: Guid): void => {
public writeGuidValue = (key?: string, value?: Guid | null): void => {
if (value === null) {
key && this.writeNullValue(key);

return;
}

if (value) {
key && this.writePropertyName(key);
this.writer.push(`"${value}"`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
}
};
public writeDateValue = (key?: string, value?: Date): void => this.writeStringValue(key, value?.toISOString());
public writeDateOnlyValue = (key?: string, value?: DateOnly): void => this.writeStringValue(key, value?.toString());
public writeTimeOnlyValue = (key?: string, value?: TimeOnly): void => this.writeStringValue(key, value?.toString());
public writeDurationValue = (key?: string, value?: Duration): void => this.writeStringValue(key, value?.toString());
public writeDateValue = (key?: string, value?: Date | null): void => this.writeStringValue(key, value === null ? null : value?.toISOString());
public writeDateOnlyValue = (key?: string, value?: DateOnly | null): void => this.writeStringValue(key, value === null ? null : value?.toString());
public writeTimeOnlyValue = (key?: string, value?: TimeOnly | null): void => this.writeStringValue(key, value === null ? null : value?.toString());
public writeDurationValue = (key?: string, value?: Duration | null): void => this.writeStringValue(key, value === null ? null : value?.toString());
public writeNullValue = (key?: string): void => {
key && this.writePropertyName(key);
this.writer.push(`null`);
key && this.writer.push(JsonSerializationWriter.propertySeparator);
};
public writeCollectionOfPrimitiveValues = <T>(key?: string, values?: T[]): void => {
if (values === null) {
key && this.writeNullValue(key);
return;
}

if (values) {
key && this.writePropertyName(key);
this.startArray();
Expand All @@ -75,6 +110,11 @@ export class JsonSerializationWriter implements SerializationWriter {
}
};
public writeCollectionOfObjectValues = <T extends Parsable>(key: string, values: T[], serializerMethod: ModelSerializerFunction<T>): void => {
baywet marked this conversation as resolved.
Show resolved Hide resolved
if (values === null) {
key && this.writeNullValue(key);
return;
}

if (values) {
key && this.writePropertyName(key);
this.startArray();
Expand Down Expand Up @@ -214,7 +254,7 @@ export class JsonSerializationWriter implements SerializationWriter {
}
this.writer.push(JSON.stringify(value), JsonSerializationWriter.propertySeparator);
};
private readonly writeAnyValue = (key?: string | undefined, value?: unknown | undefined): void => {
private readonly writeAnyValue = (key?: string | undefined, value?: unknown | null | undefined): void => {
baywet marked this conversation as resolved.
Show resolved Hide resolved
if (value !== undefined && value !== null) {
const valueType = typeof value;
if (valueType === "boolean") {
Expand Down
Loading
Loading