Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/warm-dragons-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/smithy-client": major
---

remove String extension in LazyJsonString
29 changes: 9 additions & 20 deletions packages/smithy-client/src/lazy-json.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,26 @@ import { describe, expect, test as it } from "vitest";

import { LazyJsonString } from "./lazy-json";
describe("LazyJsonString", () => {
it("should has 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("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("can instantiate from LazyJsonString class", () => {
const original = new LazyJsonString('"foo"');
const newOne = LazyJsonString.fromObject(original);
const original = LazyJsonString.from('"foo"');
const newOne = LazyJsonString.from(original);
expect(newOne.toString()).toBe('"foo"');
});

it("can instantiate from String class", () => {
const jsonValue = LazyJsonString.fromObject(new String('"foo"'));
const jsonValue = LazyJsonString.from('"foo"');
expect(jsonValue.toString()).toBe('"foo"');
});

it("can instantiate from object", () => {
const jsonValue = LazyJsonString.fromObject({ foo: "bar" });
const jsonValue = LazyJsonString.from({ foo: "bar" });
expect(jsonValue.toString()).toBe('{"foo":"bar"}');
});
});
66 changes: 24 additions & 42 deletions packages/smithy-client/src/lazy-json.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,39 @@
/**
* Lazy String holder for JSON typed contents.
*/

interface StringWrapper {
new (arg: any): String;
}

/**
* Because of https://github.com/microsoft/tslib/issues/95,
* TS 'extends' shim doesn't support extending native types like String.
* So here we create StringWrapper that duplicate everything from String
* class including its prototype chain. So we can extend from here.
*
* @internal
*
* 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.
*
*/
// @ts-ignore StringWrapper implementation is not a simple constructor
export const StringWrapper: StringWrapper = function () {
//@ts-ignore 'this' cannot be assigned to any, but Object.getPrototypeOf accepts any
const Class = Object.getPrototypeOf(this).constructor;
const Constructor = Function.bind.apply(String, [null as any, ...arguments]);
//@ts-ignore Call wrapped String constructor directly, don't bother typing it.
const instance = new Constructor();
Object.setPrototypeOf(instance, Class.prototype);
return instance as String;
};
StringWrapper.prototype = Object.create(String.prototype, {
constructor: {
value: StringWrapper,
enumerable: false,
writable: true,
configurable: true,
},
});
Object.setPrototypeOf(StringWrapper, String);
export class LazyJsonString {
private constructor(private value: string) {}

/**
* @internal
*/
export class LazyJsonString extends StringWrapper {
deserializeJSON(): any {
return JSON.parse(super.toString());
public toString(): string {
return this.value;
}

toJSON(): string {
return super.toString();
public valueOf(): string {
return this.value;
}

static fromObject(object: any): LazyJsonString {
public toJSON(): string {
return this.value;
}

public static from(object: any): LazyJsonString {
if (object instanceof LazyJsonString) {
return object;
} else if (object instanceof String || typeof object === "string") {
} else if (typeof object === "string") {
return new LazyJsonString(object);
}
return new LazyJsonString(JSON.stringify(object));
}

/**
* @deprecated call from() instead.
*/
public static fromObject(object: any): LazyJsonString {
return LazyJsonString.from(object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public static String getStringInputParam(GenerationContext context, Shape shape,
if (CodegenUtils.isJsonMediaType(mediaType)) {
TypeScriptWriter writer = context.getWriter();
writer.addImport("LazyJsonString", "__LazyJsonString", TypeScriptDependency.AWS_SMITHY_CLIENT);
return "__LazyJsonString.fromObject(" + dataSource + ")";
return "__LazyJsonString.from(" + dataSource + ")";
} else {
LOGGER.warning(() -> "Found unsupported mediatype " + mediaType + " on String shape: " + shape);
}
Expand Down Expand Up @@ -210,7 +210,7 @@ public static String getStringOutputParam(GenerationContext context,
if (CodegenUtils.isJsonMediaType(mediaType)) {
TypeScriptWriter writer = context.getWriter();
writer.addImport("LazyJsonString", "__LazyJsonString", TypeScriptDependency.AWS_SMITHY_CLIENT);
return "new __LazyJsonString(" + dataSource + ")";
return "__LazyJsonString.from(" + dataSource + ")";
} else {
LOGGER.warning(() -> "Found unsupported mediatype " + mediaType + " on String shape: " + shape);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static Collection<Object[]> validMemberTargetTypes() {
{StringShape.builder().id(id).build(), "__expectString(" + DATA_SOURCE + ")", source},
{
StringShape.builder().id(id).addTrait(new MediaTypeTrait("foo+json")).build(),
"new __LazyJsonString(" + DATA_SOURCE + ")",
"__LazyJsonString.from(" + DATA_SOURCE + ")",
source
},
{BlobShape.builder().id(id).build(), "context.base64Decoder(" + DATA_SOURCE + ")", source},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static Collection<Object[]> validMemberTargetTypes() {
{StringShape.builder().id(id).build(), DATA_SOURCE},
{
StringShape.builder().id(id).addTrait(new MediaTypeTrait("foo+json")).build(),
"__LazyJsonString.fromObject(" + DATA_SOURCE + ")"
"__LazyJsonString.from(" + DATA_SOURCE + ")"
},
{BlobShape.builder().id(id).build(), "context.base64Encoder(" + DATA_SOURCE + ")"},
{DocumentShape.builder().id(id).build(), delegate},
Expand Down
Loading