-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
86 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,39 @@ | ||
import { describe, expect, test as it } from "vitest"; | ||
|
||
import { LazyJsonString } from "./lazy-json"; | ||
|
||
describe("LazyJsonString", () => { | ||
it("returns identical values for toString(), valueOf(), and toJSON()", () => { | ||
const jsonValue = LazyJsonString.from({ foo: "bar" }); | ||
expect(jsonValue.valueOf()).toBe(JSON.stringify({ foo: "bar" })); | ||
expect(jsonValue.toString()).toBe(JSON.stringify({ foo: "bar" })); | ||
expect(jsonValue.toJSON()).toBe(JSON.stringify({ foo: "bar" })); | ||
it("should have string methods", () => { | ||
const jsonValue = new LazyJsonString('"foo"'); | ||
expect(jsonValue.length).toBe(5); | ||
expect(jsonValue.toString()).toBe('"foo"'); | ||
}); | ||
|
||
it("should deserialize json properly", () => { | ||
const jsonValue = new LazyJsonString('"foo"'); | ||
expect(jsonValue.deserializeJSON()).toBe("foo"); | ||
const wrongJsonValue = new LazyJsonString("foo"); | ||
expect(() => wrongJsonValue.deserializeJSON()).toThrow(); | ||
}); | ||
|
||
it("should get JSON string properly", () => { | ||
const jsonValue = new LazyJsonString('{"foo", "bar"}'); | ||
expect(jsonValue.toJSON()).toBe('{"foo", "bar"}'); | ||
}); | ||
|
||
it("can instantiate from LazyJsonString class", () => { | ||
const original = LazyJsonString.from('"foo"'); | ||
const newOne = LazyJsonString.from(original); | ||
const original = new LazyJsonString('"foo"'); | ||
const newOne = LazyJsonString.fromObject(original); | ||
expect(newOne.toString()).toBe('"foo"'); | ||
}); | ||
|
||
it("can instantiate from String class", () => { | ||
const jsonValue = LazyJsonString.from('"foo"'); | ||
const jsonValue = LazyJsonString.fromObject(new String('"foo"')); | ||
expect(jsonValue.toString()).toBe('"foo"'); | ||
}); | ||
|
||
it("can instantiate from object", () => { | ||
const jsonValue = LazyJsonString.from({ foo: "bar" }); | ||
const jsonValue = LazyJsonString.fromObject({ foo: "bar" }); | ||
expect(jsonValue.toString()).toBe('{"foo":"bar"}'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,68 @@ | ||
/** | ||
* @internal | ||
* @public | ||
* | ||
* This class allows the usage of data objects in fields that expect | ||
* JSON strings. It serializes the data object into JSON | ||
* if needed during the request serialization step. | ||
* A model field with this type means that you may provide a JavaScript | ||
* object in lieu of a JSON string, and it will be serialized to JSON | ||
* automatically before being sent in a request. | ||
* | ||
* For responses, you will receive a "LazyJsonString", which is a boxed String object | ||
* with additional mixin methods. | ||
* To get the string value, call `.toString()`, or to get the JSON object value, | ||
* call `.deserializeJSON()` or parse it yourself. | ||
*/ | ||
export class LazyJsonString { | ||
private constructor(private value: string) {} | ||
|
||
public toString(): string { | ||
return this.value; | ||
} | ||
export type AutomaticJsonStringConversion = Parameters<typeof JSON.stringify>[0] | LazyJsonString; | ||
|
||
public valueOf(): string { | ||
return this.value; | ||
} | ||
|
||
public toJSON(): string { | ||
return this.value; | ||
} | ||
/** | ||
* @internal | ||
* | ||
*/ | ||
export interface LazyJsonString extends String { | ||
new (s: string): typeof LazyJsonString; | ||
|
||
public static from(object: any): LazyJsonString { | ||
if (object instanceof LazyJsonString) { | ||
return object; | ||
} else if (typeof object === "string") { | ||
return new LazyJsonString(object); | ||
} | ||
return new LazyJsonString(JSON.stringify(object)); | ||
} | ||
/** | ||
* @returns the JSON parsing of the string value. | ||
*/ | ||
deserializeJSON(): any; | ||
|
||
/** | ||
* @deprecated call from() instead. | ||
* @returns the original string value rather than a JSON.stringified value. | ||
*/ | ||
public static fromObject(object: any): LazyJsonString { | ||
return LazyJsonString.from(object); | ||
} | ||
toJSON(): string; | ||
} | ||
|
||
/** | ||
* @internal | ||
* | ||
* Extension of the native String class in the previous implementation | ||
* has negative global performance impact on method dispatch for strings, | ||
* and is generally discouraged. | ||
* | ||
* This current implementation may look strange, but is necessary to preserve the interface and | ||
* behavior of extending the String class. | ||
*/ | ||
export function LazyJsonString(val: string): void { | ||
const str = Object.assign(new String(val), { | ||
deserializeJSON() { | ||
return JSON.parse(val); | ||
}, | ||
|
||
toString() { | ||
return val; | ||
}, | ||
|
||
toJSON() { | ||
return val; | ||
}, | ||
}); | ||
|
||
return str as never; | ||
} | ||
|
||
LazyJsonString.fromObject = (object: any): LazyJsonString => { | ||
if (object instanceof LazyJsonString) { | ||
return object as any; | ||
} else if (typeof object === "string" || object?.prototype === String.prototype) { | ||
return LazyJsonString(object as string) as any; | ||
} | ||
return LazyJsonString(JSON.stringify(object)) as any; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters