diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts
index 49d91b6bbc..8a21f271bd 100644
--- a/packages/jsii-calc/lib/compliance.ts
+++ b/packages/jsii-calc/lib/compliance.ts
@@ -2175,3 +2175,36 @@ class PrivateBell implements IBell {
this.rung = true;
}
}
+
+/**
+ * This is here to check that we can pass a nested struct into a kwargs by specifying it as an
+ * in-line dictionary. This is cheating with the declared types, but Python people don't play by
+ * the rules much apparently.
+ */
+export interface RootStruct {
+ /**
+ * May not be empty.
+ */
+ readonly stringProp: string;
+ readonly nestedStruct?: NestedStruct;
+}
+export interface NestedStruct {
+ /**
+ * When provided, must be > 0.
+ */
+ readonly numberProp: number;
+}
+export class RootStructValidator {
+ public static validate(struct: RootStruct): void {
+ if (!struct.stringProp) {
+ throw new Error('Missing required field: stringProp');
+ }
+ if (struct.nestedStruct) {
+ if (struct.nestedStruct.numberProp <= 0) {
+ throw new Error('numberProp must be > 0');
+ }
+ }
+ }
+
+ private constructor() { }
+}
diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii
index 951dc349a5..5550b1c509 100644
--- a/packages/jsii-calc/test/assembly.jsii
+++ b/packages/jsii-calc/test/assembly.jsii
@@ -6799,6 +6799,38 @@
}
]
},
+ "jsii-calc.NestedStruct": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "docs": {
+ "stability": "experimental"
+ },
+ "fqn": "jsii-calc.NestedStruct",
+ "kind": "interface",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2191
+ },
+ "name": "NestedStruct",
+ "properties": [
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental",
+ "summary": "When provided, must be > 0."
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2195
+ },
+ "name": "numberProp",
+ "type": {
+ "primitive": "number"
+ }
+ }
+ ]
+ },
"jsii-calc.NodeStandardLibrary": {
"assembly": "jsii-calc",
"docs": {
@@ -8215,6 +8247,90 @@
}
]
},
+ "jsii-calc.RootStruct": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "docs": {
+ "remarks": "This is cheating with the declared types, but Python people don't play by\nthe rules much apparently.",
+ "stability": "experimental",
+ "summary": "This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary."
+ },
+ "fqn": "jsii-calc.RootStruct",
+ "kind": "interface",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2184
+ },
+ "name": "RootStruct",
+ "properties": [
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental",
+ "summary": "May not be empty."
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2188
+ },
+ "name": "stringProp",
+ "type": {
+ "primitive": "string"
+ }
+ },
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental"
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2189
+ },
+ "name": "nestedStruct",
+ "optional": true,
+ "type": {
+ "fqn": "jsii-calc.NestedStruct"
+ }
+ }
+ ]
+ },
+ "jsii-calc.RootStructValidator": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "stability": "experimental"
+ },
+ "fqn": "jsii-calc.RootStructValidator",
+ "kind": "class",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2197
+ },
+ "methods": [
+ {
+ "docs": {
+ "stability": "experimental"
+ },
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2198
+ },
+ "name": "validate",
+ "parameters": [
+ {
+ "name": "struct",
+ "type": {
+ "fqn": "jsii-calc.RootStruct"
+ }
+ }
+ ],
+ "static": true
+ }
+ ],
+ "name": "RootStructValidator"
+ },
"jsii-calc.RuntimeTypeChecking": {
"assembly": "jsii-calc",
"docs": {
@@ -10797,5 +10913,5 @@
}
},
"version": "0.20.3",
- "fingerprint": "r/K0k7ocrPmzUuFsCAvxLY2UdNEi6r/ruaoO3PnHiCA="
+ "fingerprint": "1F+uskR3++T5mjRcWge9oG3H/jJvXm1C3IhR1AwsBTE="
}
diff --git a/packages/jsii-kernel/lib/serialization.ts b/packages/jsii-kernel/lib/serialization.ts
index 3c87b1bea5..4961b1cb8d 100644
--- a/packages/jsii-kernel/lib/serialization.ts
+++ b/packages/jsii-kernel/lib/serialization.ts
@@ -360,6 +360,11 @@ export const SERIALIZERS: {[k: string]: Serializer} = {
value = data;
}
+ // Python, for example, allows using plain mapping objects instead of Structs (dyanmic typing, YOLO!)
+ if (api.isWireMap(value)) {
+ value = value[api.TOKEN_MAP];
+ }
+
value = validateRequiredProps(value as any, namedType.fqn, props);
// Return a dict COPY, we have by-value semantics anyway.
diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts
index 54bfeab317..d9032d23a7 100644
--- a/packages/jsii-pacmak/lib/targets/python.ts
+++ b/packages/jsii-pacmak/lib/targets/python.ts
@@ -661,6 +661,13 @@ class Struct extends BasePythonClassType {
code.openBlock(`def __init__(${constructorArguments.join(', ')})`);
this.emitConstructorDocstring(code);
+ // Re-type struct arguments that were passed as "dict"
+ for (const member of members.filter(m => m.isStruct(this.generator))) {
+ // Note that "None" is NOT an instance of dict (that's convenient!)
+ const typeName = resolver.resolve(member.type, { ignoreOptional: true });
+ code.line(`if isinstance(${member.pythonName}, dict): ${member.pythonName} = ${typeName}(**${member.pythonName})`);
+ }
+
// Required properties, those will always be put into the dict
code.line('self._values = {');
for (const member of members.filter(m => !m.optional)) {
@@ -719,7 +726,7 @@ class StructField implements PythonBase {
public readonly pythonName: string;
public readonly jsiiName: string;
public readonly docs?: spec.Docs;
- private readonly type: spec.OptionalValue;
+ public readonly type: spec.OptionalValue;
public constructor(public readonly prop: spec.Property) {
this.pythonName = toPythonPropertyName(prop.name);
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii
index 951dc349a5..5550b1c509 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii
@@ -6799,6 +6799,38 @@
}
]
},
+ "jsii-calc.NestedStruct": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "docs": {
+ "stability": "experimental"
+ },
+ "fqn": "jsii-calc.NestedStruct",
+ "kind": "interface",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2191
+ },
+ "name": "NestedStruct",
+ "properties": [
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental",
+ "summary": "When provided, must be > 0."
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2195
+ },
+ "name": "numberProp",
+ "type": {
+ "primitive": "number"
+ }
+ }
+ ]
+ },
"jsii-calc.NodeStandardLibrary": {
"assembly": "jsii-calc",
"docs": {
@@ -8215,6 +8247,90 @@
}
]
},
+ "jsii-calc.RootStruct": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "docs": {
+ "remarks": "This is cheating with the declared types, but Python people don't play by\nthe rules much apparently.",
+ "stability": "experimental",
+ "summary": "This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary."
+ },
+ "fqn": "jsii-calc.RootStruct",
+ "kind": "interface",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2184
+ },
+ "name": "RootStruct",
+ "properties": [
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental",
+ "summary": "May not be empty."
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2188
+ },
+ "name": "stringProp",
+ "type": {
+ "primitive": "string"
+ }
+ },
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "experimental"
+ },
+ "immutable": true,
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2189
+ },
+ "name": "nestedStruct",
+ "optional": true,
+ "type": {
+ "fqn": "jsii-calc.NestedStruct"
+ }
+ }
+ ]
+ },
+ "jsii-calc.RootStructValidator": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "stability": "experimental"
+ },
+ "fqn": "jsii-calc.RootStructValidator",
+ "kind": "class",
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2197
+ },
+ "methods": [
+ {
+ "docs": {
+ "stability": "experimental"
+ },
+ "locationInModule": {
+ "filename": "lib/compliance.ts",
+ "line": 2198
+ },
+ "name": "validate",
+ "parameters": [
+ {
+ "name": "struct",
+ "type": {
+ "fqn": "jsii-calc.RootStruct"
+ }
+ }
+ ],
+ "static": true
+ }
+ ],
+ "name": "RootStructValidator"
+ },
"jsii-calc.RuntimeTypeChecking": {
"assembly": "jsii-calc",
"docs": {
@@ -10797,5 +10913,5 @@
}
},
"version": "0.20.3",
- "fingerprint": "r/K0k7ocrPmzUuFsCAvxLY2UdNEi6r/ruaoO3PnHiCA="
+ "fingerprint": "1F+uskR3++T5mjRcWge9oG3H/jJvXm1C3IhR1AwsBTE="
}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INestedStruct.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INestedStruct.cs
new file mode 100644
index 0000000000..6071669e9f
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INestedStruct.cs
@@ -0,0 +1,21 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiInterface(nativeType: typeof(INestedStruct), fullyQualifiedName: "jsii-calc.NestedStruct")]
+ public interface INestedStruct
+ {
+ /// When provided, must be > 0.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "numberProp", typeJson: "{\"primitive\":\"number\"}")]
+ double NumberProp
+ {
+ get;
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IRootStruct.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IRootStruct.cs
new file mode 100644
index 0000000000..8da60016ad
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IRootStruct.cs
@@ -0,0 +1,37 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ /// This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary.
+ ///
+ /// This is cheating with the declared types, but Python people don't play by
+ /// the rules much apparently.
+ /// stability: Experimental
+ ///
+ [JsiiInterface(nativeType: typeof(IRootStruct), fullyQualifiedName: "jsii-calc.RootStruct")]
+ public interface IRootStruct
+ {
+ /// May not be empty.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "stringProp", typeJson: "{\"primitive\":\"string\"}")]
+ string StringProp
+ {
+ get;
+ }
+
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "nestedStruct", typeJson: "{\"fqn\":\"jsii-calc.NestedStruct\"}", isOptional: true)]
+ [Amazon.JSII.Runtime.Deputy.JsiiOptional]
+ Amazon.JSII.Tests.CalculatorNamespace.INestedStruct NestedStruct
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStruct.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStruct.cs
new file mode 100644
index 0000000000..172b65ed76
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStruct.cs
@@ -0,0 +1,22 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiByValue(fqn: "jsii-calc.NestedStruct")]
+ public class NestedStruct : Amazon.JSII.Tests.CalculatorNamespace.INestedStruct
+ {
+ /// When provided, must be > 0.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "numberProp", typeJson: "{\"primitive\":\"number\"}", isOverride: true)]
+ public double NumberProp
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStructProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStructProxy.cs
new file mode 100644
index 0000000000..88ca5ac977
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NestedStructProxy.cs
@@ -0,0 +1,25 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiTypeProxy(nativeType: typeof(INestedStruct), fullyQualifiedName: "jsii-calc.NestedStruct")]
+ internal sealed class NestedStructProxy : DeputyBase, Amazon.JSII.Tests.CalculatorNamespace.INestedStruct
+ {
+ private NestedStructProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// When provided, must be > 0.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "numberProp", typeJson: "{\"primitive\":\"number\"}")]
+ public double NumberProp
+ {
+ get => GetInstanceProperty();
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStruct.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStruct.cs
new file mode 100644
index 0000000000..9758519697
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStruct.cs
@@ -0,0 +1,36 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ /// This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary.
+ ///
+ /// This is cheating with the declared types, but Python people don't play by
+ /// the rules much apparently.
+ /// stability: Experimental
+ ///
+ [JsiiByValue(fqn: "jsii-calc.RootStruct")]
+ public class RootStruct : Amazon.JSII.Tests.CalculatorNamespace.IRootStruct
+ {
+ /// May not be empty.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "stringProp", typeJson: "{\"primitive\":\"string\"}", isOverride: true)]
+ public string StringProp
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiOptional]
+ [JsiiProperty(name: "nestedStruct", typeJson: "{\"fqn\":\"jsii-calc.NestedStruct\"}", isOptional: true, isOverride: true)]
+ public Amazon.JSII.Tests.CalculatorNamespace.INestedStruct NestedStruct
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructProxy.cs
new file mode 100644
index 0000000000..7816bebc5a
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructProxy.cs
@@ -0,0 +1,38 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ /// This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary.
+ ///
+ /// This is cheating with the declared types, but Python people don't play by
+ /// the rules much apparently.
+ /// stability: Experimental
+ ///
+ [JsiiTypeProxy(nativeType: typeof(IRootStruct), fullyQualifiedName: "jsii-calc.RootStruct")]
+ internal sealed class RootStructProxy : DeputyBase, Amazon.JSII.Tests.CalculatorNamespace.IRootStruct
+ {
+ private RootStructProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// May not be empty.
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiProperty(name: "stringProp", typeJson: "{\"primitive\":\"string\"}")]
+ public string StringProp
+ {
+ get => GetInstanceProperty();
+ }
+
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiOptional]
+ [JsiiProperty(name: "nestedStruct", typeJson: "{\"fqn\":\"jsii-calc.NestedStruct\"}", isOptional: true)]
+ public Amazon.JSII.Tests.CalculatorNamespace.INestedStruct NestedStruct
+ {
+ get => GetInstanceProperty();
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructValidator.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructValidator.cs
new file mode 100644
index 0000000000..69bfd315bf
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/RootStructValidator.cs
@@ -0,0 +1,28 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiClass(nativeType: typeof(Amazon.JSII.Tests.CalculatorNamespace.RootStructValidator), fullyQualifiedName: "jsii-calc.RootStructValidator")]
+ public class RootStructValidator : DeputyBase
+ {
+ protected RootStructValidator(ByRefValue reference): base(reference)
+ {
+ }
+
+ protected RootStructValidator(DeputyProps props): base(props)
+ {
+ }
+
+ ///
+ /// stability: Experimental
+ ///
+ [JsiiMethod(name: "validate", parametersJson: "[{\"name\":\"struct\",\"type\":{\"fqn\":\"jsii-calc.RootStruct\"}}]")]
+ public static void Validate(Amazon.JSII.Tests.CalculatorNamespace.IRootStruct @struct)
+ {
+ InvokeStaticVoidMethod(typeof(Amazon.JSII.Tests.CalculatorNamespace.RootStructValidator), new System.Type[]{typeof(Amazon.JSII.Tests.CalculatorNamespace.IRootStruct)}, new object[]{@struct});
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java
index be82ab3d32..9c27fed73b 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java
@@ -125,6 +125,7 @@ protected Class> resolveClass(final String fqn) throws ClassNotFoundException
case "jsii-calc.LoadBalancedFargateServiceProps": return software.amazon.jsii.tests.calculator.LoadBalancedFargateServiceProps.class;
case "jsii-calc.Multiply": return software.amazon.jsii.tests.calculator.Multiply.class;
case "jsii-calc.Negate": return software.amazon.jsii.tests.calculator.Negate.class;
+ case "jsii-calc.NestedStruct": return software.amazon.jsii.tests.calculator.NestedStruct.class;
case "jsii-calc.NodeStandardLibrary": return software.amazon.jsii.tests.calculator.NodeStandardLibrary.class;
case "jsii-calc.NullShouldBeTreatedAsUndefined": return software.amazon.jsii.tests.calculator.NullShouldBeTreatedAsUndefined.class;
case "jsii-calc.NullShouldBeTreatedAsUndefinedData": return software.amazon.jsii.tests.calculator.NullShouldBeTreatedAsUndefinedData.class;
@@ -144,6 +145,8 @@ protected Class> resolveClass(final String fqn) throws ClassNotFoundException
case "jsii-calc.PythonReservedWords": return software.amazon.jsii.tests.calculator.PythonReservedWords.class;
case "jsii-calc.ReferenceEnumFromScopedPackage": return software.amazon.jsii.tests.calculator.ReferenceEnumFromScopedPackage.class;
case "jsii-calc.ReturnsPrivateImplementationOfInterface": return software.amazon.jsii.tests.calculator.ReturnsPrivateImplementationOfInterface.class;
+ case "jsii-calc.RootStruct": return software.amazon.jsii.tests.calculator.RootStruct.class;
+ case "jsii-calc.RootStructValidator": return software.amazon.jsii.tests.calculator.RootStructValidator.class;
case "jsii-calc.RuntimeTypeChecking": return software.amazon.jsii.tests.calculator.RuntimeTypeChecking.class;
case "jsii-calc.SecondLevelStruct": return software.amazon.jsii.tests.calculator.SecondLevelStruct.class;
case "jsii-calc.SingleInstanceTwoTypes": return software.amazon.jsii.tests.calculator.SingleInstanceTwoTypes.class;
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NestedStruct.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NestedStruct.java
new file mode 100644
index 0000000000..8671fb1fd4
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NestedStruct.java
@@ -0,0 +1,118 @@
+package software.amazon.jsii.tests.calculator;
+
+/**
+ * EXPERIMENTAL
+ */
+@javax.annotation.Generated(value = "jsii-pacmak")
+@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.NestedStruct")
+@software.amazon.jsii.Jsii.Proxy(NestedStruct.Jsii$Proxy.class)
+@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+public interface NestedStruct extends software.amazon.jsii.JsiiSerializable {
+
+ /**
+ * When provided, must be > 0.
+ *
+ * EXPERIMENTAL
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ java.lang.Number getNumberProp();
+
+ /**
+ * @return a {@link Builder} of {@link NestedStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ static Builder builder() {
+ return new Builder();
+ }
+ /**
+ * A builder for {@link NestedStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public static final class Builder {
+ private java.lang.Number numberProp;
+
+ /**
+ * Sets the value of NumberProp
+ * @param numberProp When provided, must be > 0. This parameter is required.
+ * @return {@code this}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public Builder numberProp(java.lang.Number numberProp) {
+ this.numberProp = numberProp;
+ return this;
+ }
+
+ /**
+ * Builds the configured instance.
+ * @return a new instance of {@link NestedStruct}
+ * @throws NullPointerException if any required attribute was not provided
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public NestedStruct build() {
+ return new Jsii$Proxy(numberProp);
+ }
+ }
+
+ /**
+ * An implementation for {@link NestedStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ final class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements NestedStruct {
+ private final java.lang.Number numberProp;
+
+ /**
+ * Constructor that initializes the object based on values retrieved from the JsiiObject.
+ * @param objRef Reference to the JSII managed object.
+ */
+ protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) {
+ super(objRef);
+ this.numberProp = this.jsiiGet("numberProp", java.lang.Number.class);
+ }
+
+ /**
+ * Constructor that initializes the object based on literal property values passed by the {@link Builder}.
+ */
+ private Jsii$Proxy(final java.lang.Number numberProp) {
+ super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);
+ this.numberProp = java.util.Objects.requireNonNull(numberProp, "numberProp is required");
+ }
+
+ @Override
+ public java.lang.Number getNumberProp() {
+ return this.numberProp;
+ }
+
+ @Override
+ public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() {
+ final com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE;
+ final com.fasterxml.jackson.databind.node.ObjectNode data = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+
+ data.set("numberProp", om.valueToTree(this.getNumberProp()));
+
+ final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+ struct.set("fqn", om.valueToTree("jsii-calc.NestedStruct"));
+ struct.set("data", data);
+
+ final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+ obj.set("$jsii.struct", struct);
+
+ return obj;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ NestedStruct.Jsii$Proxy that = (NestedStruct.Jsii$Proxy) o;
+
+ return this.numberProp.equals(that.numberProp);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = this.numberProp.hashCode();
+ return result;
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStruct.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStruct.java
new file mode 100644
index 0000000000..0f00c684db
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStruct.java
@@ -0,0 +1,156 @@
+package software.amazon.jsii.tests.calculator;
+
+/**
+ * This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary.
+ *
+ * This is cheating with the declared types, but Python people don't play by
+ * the rules much apparently.
+ *
+ * EXPERIMENTAL
+ */
+@javax.annotation.Generated(value = "jsii-pacmak")
+@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.RootStruct")
+@software.amazon.jsii.Jsii.Proxy(RootStruct.Jsii$Proxy.class)
+@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+public interface RootStruct extends software.amazon.jsii.JsiiSerializable {
+
+ /**
+ * May not be empty.
+ *
+ * EXPERIMENTAL
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ java.lang.String getStringProp();
+
+ /**
+ * EXPERIMENTAL
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ default software.amazon.jsii.tests.calculator.NestedStruct getNestedStruct() {
+ return null;
+ }
+
+ /**
+ * @return a {@link Builder} of {@link RootStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ static Builder builder() {
+ return new Builder();
+ }
+ /**
+ * A builder for {@link RootStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public static final class Builder {
+ private java.lang.String stringProp;
+ private software.amazon.jsii.tests.calculator.NestedStruct nestedStruct;
+
+ /**
+ * Sets the value of StringProp
+ * @param stringProp May not be empty. This parameter is required.
+ * @return {@code this}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public Builder stringProp(java.lang.String stringProp) {
+ this.stringProp = stringProp;
+ return this;
+ }
+
+ /**
+ * Sets the value of NestedStruct
+ * @param nestedStruct the value to be set.
+ * @return {@code this}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public Builder nestedStruct(software.amazon.jsii.tests.calculator.NestedStruct nestedStruct) {
+ this.nestedStruct = nestedStruct;
+ return this;
+ }
+
+ /**
+ * Builds the configured instance.
+ * @return a new instance of {@link RootStruct}
+ * @throws NullPointerException if any required attribute was not provided
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public RootStruct build() {
+ return new Jsii$Proxy(stringProp, nestedStruct);
+ }
+ }
+
+ /**
+ * An implementation for {@link RootStruct}
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ final class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements RootStruct {
+ private final java.lang.String stringProp;
+ private final software.amazon.jsii.tests.calculator.NestedStruct nestedStruct;
+
+ /**
+ * Constructor that initializes the object based on values retrieved from the JsiiObject.
+ * @param objRef Reference to the JSII managed object.
+ */
+ protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) {
+ super(objRef);
+ this.stringProp = this.jsiiGet("stringProp", java.lang.String.class);
+ this.nestedStruct = this.jsiiGet("nestedStruct", software.amazon.jsii.tests.calculator.NestedStruct.class);
+ }
+
+ /**
+ * Constructor that initializes the object based on literal property values passed by the {@link Builder}.
+ */
+ private Jsii$Proxy(final java.lang.String stringProp, final software.amazon.jsii.tests.calculator.NestedStruct nestedStruct) {
+ super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);
+ this.stringProp = java.util.Objects.requireNonNull(stringProp, "stringProp is required");
+ this.nestedStruct = nestedStruct;
+ }
+
+ @Override
+ public java.lang.String getStringProp() {
+ return this.stringProp;
+ }
+
+ @Override
+ public software.amazon.jsii.tests.calculator.NestedStruct getNestedStruct() {
+ return this.nestedStruct;
+ }
+
+ @Override
+ public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() {
+ final com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE;
+ final com.fasterxml.jackson.databind.node.ObjectNode data = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+
+ data.set("stringProp", om.valueToTree(this.getStringProp()));
+ if (this.getNestedStruct() != null) {
+ data.set("nestedStruct", om.valueToTree(this.getNestedStruct()));
+ }
+
+ final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+ struct.set("fqn", om.valueToTree("jsii-calc.RootStruct"));
+ struct.set("data", data);
+
+ final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();
+ obj.set("$jsii.struct", struct);
+
+ return obj;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ RootStruct.Jsii$Proxy that = (RootStruct.Jsii$Proxy) o;
+
+ if (!stringProp.equals(that.stringProp)) return false;
+ return this.nestedStruct != null ? this.nestedStruct.equals(that.nestedStruct) : that.nestedStruct == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = this.stringProp.hashCode();
+ result = 31 * result + (this.nestedStruct != null ? this.nestedStruct.hashCode() : 0);
+ return result;
+ }
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStructValidator.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStructValidator.java
new file mode 100644
index 0000000000..c6a862f870
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/RootStructValidator.java
@@ -0,0 +1,28 @@
+package software.amazon.jsii.tests.calculator;
+
+/**
+ * EXPERIMENTAL
+ */
+@javax.annotation.Generated(value = "jsii-pacmak")
+@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.RootStructValidator")
+public class RootStructValidator extends software.amazon.jsii.JsiiObject {
+
+ protected RootStructValidator(final software.amazon.jsii.JsiiObjectRef objRef) {
+ super(objRef);
+ }
+
+ protected RootStructValidator(final software.amazon.jsii.JsiiObject.InitializationMode initializationMode) {
+ super(initializationMode);
+ }
+
+ /**
+ * EXPERIMENTAL
+ *
+ * @param struct This parameter is required.
+ */
+ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
+ public static void validate(final software.amazon.jsii.tests.calculator.RootStruct struct) {
+ software.amazon.jsii.JsiiObject.jsiiStaticCall(software.amazon.jsii.tests.calculator.RootStructValidator.class, "validate", Void.class, new Object[] { java.util.Objects.requireNonNull(struct, "struct is required") });
+ }
+}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py
index 61ab803b61..6a52bf4e90 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py
@@ -4875,6 +4875,38 @@ def value(self) -> jsii.Number:
return jsii.get(self, "value")
+@jsii.data_type(jsii_type="jsii-calc.NestedStruct", jsii_struct_bases=[], name_mapping={'number_prop': 'numberProp'})
+class NestedStruct():
+ def __init__(self, *, number_prop: jsii.Number):
+ """
+ :param number_prop: When provided, must be > 0.
+
+ stability
+ :stability: experimental
+ """
+ self._values = {
+ 'number_prop': number_prop,
+ }
+
+ @property
+ def number_prop(self) -> jsii.Number:
+ """When provided, must be > 0.
+
+ stability
+ :stability: experimental
+ """
+ return self._values.get('number_prop')
+
+ def __eq__(self, rhs) -> bool:
+ return isinstance(rhs, self.__class__) and rhs._values == self._values
+
+ def __ne__(self, rhs) -> bool:
+ return not (rhs == self)
+
+ def __repr__(self) -> str:
+ return 'NestedStruct(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())
+
+
class NodeStandardLibrary(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.NodeStandardLibrary"):
"""Test fixture to verify that jsii modules can use the node standard library.
@@ -5777,6 +5809,74 @@ def private_implementation(self) -> "IPrivatelyImplemented":
return jsii.get(self, "privateImplementation")
+@jsii.data_type(jsii_type="jsii-calc.RootStruct", jsii_struct_bases=[], name_mapping={'string_prop': 'stringProp', 'nested_struct': 'nestedStruct'})
+class RootStruct():
+ def __init__(self, *, string_prop: str, nested_struct: typing.Optional["NestedStruct"]=None):
+ """This is here to check that we can pass a nested struct into a kwargs by specifying it as an in-line dictionary.
+
+ This is cheating with the declared types, but Python people don't play by
+ the rules much apparently.
+
+ :param string_prop: May not be empty.
+ :param nested_struct:
+
+ stability
+ :stability: experimental
+ """
+ if isinstance(nested_struct, dict): nested_struct = NestedStruct(**nested_struct)
+ self._values = {
+ 'string_prop': string_prop,
+ }
+ if nested_struct is not None: self._values["nested_struct"] = nested_struct
+
+ @property
+ def string_prop(self) -> str:
+ """May not be empty.
+
+ stability
+ :stability: experimental
+ """
+ return self._values.get('string_prop')
+
+ @property
+ def nested_struct(self) -> typing.Optional["NestedStruct"]:
+ """
+ stability
+ :stability: experimental
+ """
+ return self._values.get('nested_struct')
+
+ def __eq__(self, rhs) -> bool:
+ return isinstance(rhs, self.__class__) and rhs._values == self._values
+
+ def __ne__(self, rhs) -> bool:
+ return not (rhs == self)
+
+ def __repr__(self) -> str:
+ return 'RootStruct(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())
+
+
+class RootStructValidator(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.RootStructValidator"):
+ """
+ stability
+ :stability: experimental
+ """
+ @jsii.member(jsii_name="validate")
+ @classmethod
+ def validate(cls, *, string_prop: str, nested_struct: typing.Optional["NestedStruct"]=None) -> None:
+ """
+ :param struct: -
+ :param string_prop: May not be empty.
+ :param nested_struct:
+
+ stability
+ :stability: experimental
+ """
+ struct = RootStruct(string_prop=string_prop, nested_struct=nested_struct)
+
+ return jsii.sinvoke(cls, "validate", [struct])
+
+
class RuntimeTypeChecking(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.RuntimeTypeChecking"):
"""
stability
@@ -6265,6 +6365,7 @@ def __init__(self, *, required_string: str, optional_boolean: typing.Optional[bo
stability
:stability: experimental
"""
+ if isinstance(optional_struct_a, dict): optional_struct_a = StructA(**optional_struct_a)
self._values = {
'required_string': required_string,
}
@@ -7558,6 +7659,6 @@ def parts(self, value: typing.List[scope.jsii_calc_lib.Value]):
return jsii.set(self, "parts", value)
-__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AnonymousImplementationProvider", "AsyncVirtualMethods", "AugmentableClass", "Bell", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithCollections", "ClassWithDocs", "ClassWithJavaReservedWords", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "ConstructorPassesThisOut", "Constructors", "ConsumerCanRingBell", "ConsumersOfThisCrazyTypeSystem", "DataRenderer", "DefaultedConstructorArgument", "DeprecatedClass", "DeprecatedEnum", "DeprecatedStruct", "DerivedClassHasNoProperties", "DerivedStruct", "DiamondInheritanceBaseLevelStruct", "DiamondInheritanceFirstMidLevelStruct", "DiamondInheritanceSecondMidLevelStruct", "DiamondInheritanceTopLevelStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DocumentedClass", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EnumDispenser", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExperimentalClass", "ExperimentalEnum", "ExperimentalStruct", "ExportedBaseClass", "ExtendsInternalInterface", "GiveMeStructs", "Greetee", "GreetingAugmenter", "IAnonymousImplementationProvider", "IAnonymouslyImplementMe", "IAnotherPublicInterface", "IBell", "IBellRinger", "IConcreteBellRinger", "IDeprecatedInterface", "IExperimentalInterface", "IExtendsPrivateInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceImplementedByAbstractClass", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IJSII417Derived", "IJSII417PublicBaseOfBase", "IJsii487External", "IJsii487External2", "IJsii496", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "IStableInterface", "ImplementInternalInterface", "Implementation", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "InterfacesMaker", "JSII417Derived", "JSII417PublicBaseOfBase", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "Jsii487Derived", "Jsii496Derived", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "Old", "OptionalArgumentInvoker", "OptionalConstructorArgument", "OptionalStruct", "OptionalStructConsumer", "OverridableProtectedMember", "OverrideReturnsObject", "PartiallyInitializedThisConsumer", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RuntimeTypeChecking", "SecondLevelStruct", "SingleInstanceTwoTypes", "SingletonInt", "SingletonIntEnum", "SingletonString", "SingletonStringEnum", "StableClass", "StableEnum", "StableStruct", "StaticContext", "Statics", "StringEnum", "StripInternal", "StructA", "StructB", "StructPassing", "StructUnionConsumer", "StructWithJavaReservedWords", "Sum", "SupportsNiceJavaBuilder", "SupportsNiceJavaBuilderProps", "SupportsNiceJavaBuilderWithRequiredProps", "SyncVirtualMethods", "Thrower", "TopLevelStruct", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicInvoker", "VariadicMethod", "VirtualMethodPlayground", "VoidCallback", "WithPrivatePropertyInConstructor", "__jsii_assembly__", "composition"]
+__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AnonymousImplementationProvider", "AsyncVirtualMethods", "AugmentableClass", "Bell", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithCollections", "ClassWithDocs", "ClassWithJavaReservedWords", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "ConstructorPassesThisOut", "Constructors", "ConsumerCanRingBell", "ConsumersOfThisCrazyTypeSystem", "DataRenderer", "DefaultedConstructorArgument", "DeprecatedClass", "DeprecatedEnum", "DeprecatedStruct", "DerivedClassHasNoProperties", "DerivedStruct", "DiamondInheritanceBaseLevelStruct", "DiamondInheritanceFirstMidLevelStruct", "DiamondInheritanceSecondMidLevelStruct", "DiamondInheritanceTopLevelStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DocumentedClass", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EnumDispenser", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExperimentalClass", "ExperimentalEnum", "ExperimentalStruct", "ExportedBaseClass", "ExtendsInternalInterface", "GiveMeStructs", "Greetee", "GreetingAugmenter", "IAnonymousImplementationProvider", "IAnonymouslyImplementMe", "IAnotherPublicInterface", "IBell", "IBellRinger", "IConcreteBellRinger", "IDeprecatedInterface", "IExperimentalInterface", "IExtendsPrivateInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceImplementedByAbstractClass", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IJSII417Derived", "IJSII417PublicBaseOfBase", "IJsii487External", "IJsii487External2", "IJsii496", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "IStableInterface", "ImplementInternalInterface", "Implementation", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "InterfacesMaker", "JSII417Derived", "JSII417PublicBaseOfBase", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "Jsii487Derived", "Jsii496Derived", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NestedStruct", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "Old", "OptionalArgumentInvoker", "OptionalConstructorArgument", "OptionalStruct", "OptionalStructConsumer", "OverridableProtectedMember", "OverrideReturnsObject", "PartiallyInitializedThisConsumer", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RootStruct", "RootStructValidator", "RuntimeTypeChecking", "SecondLevelStruct", "SingleInstanceTwoTypes", "SingletonInt", "SingletonIntEnum", "SingletonString", "SingletonStringEnum", "StableClass", "StableEnum", "StableStruct", "StaticContext", "Statics", "StringEnum", "StripInternal", "StructA", "StructB", "StructPassing", "StructUnionConsumer", "StructWithJavaReservedWords", "Sum", "SupportsNiceJavaBuilder", "SupportsNiceJavaBuilderProps", "SupportsNiceJavaBuilderWithRequiredProps", "SyncVirtualMethods", "Thrower", "TopLevelStruct", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicInvoker", "VariadicMethod", "VirtualMethodPlayground", "VoidCallback", "WithPrivatePropertyInConstructor", "__jsii_assembly__", "composition"]
publication.publish()
diff --git a/packages/jsii-python-runtime/tests/test_compliance.py b/packages/jsii-python-runtime/tests/test_compliance.py
index 7895a6cfdd..6c63c97889 100644
--- a/packages/jsii-python-runtime/tests/test_compliance.py
+++ b/packages/jsii-python-runtime/tests/test_compliance.py
@@ -48,6 +48,8 @@
EraseUndefinedHashValues,
EraseUndefinedHashValuesOptions,
VariadicMethod,
+ RootStruct,
+ RootStructValidator,
StructPassing,
TopLevelStruct,
SecondLevelStruct,
@@ -1000,6 +1002,16 @@ def test_consumer_calls_method_privateclass():
def test_consumer_calls_method_typed_as_class():
assert ConsumerCanRingBell().when_typed_as_class(PythonConcreteBellRinger())
+def test_can_pass_nested_struct_as_dict():
+ # Those shouldn't raise:
+ RootStructValidator.validate(string_prop= 'Pickle Rick!!!')
+ RootStructValidator.validate(string_prop= 'Pickle Rick!!!', nested_struct= None)
+ RootStructValidator.validate(
+ string_prop= 'Pickle Rick!!!',
+ nested_struct= {
+ 'number_prop': 1337
+ }
+ )
@jsii.implements(IBellRinger)
class PythonBellRinger:
diff --git a/packages/jsii-reflect/test/__snapshots__/jsii-tree.test.js.snap b/packages/jsii-reflect/test/__snapshots__/jsii-tree.test.js.snap
index 4eeb29d4e8..5ddff0ad79 100644
--- a/packages/jsii-reflect/test/__snapshots__/jsii-tree.test.js.snap
+++ b/packages/jsii-reflect/test/__snapshots__/jsii-tree.test.js.snap
@@ -1126,6 +1126,14 @@ exports[`jsii-tree --all 1`] = `
│ │ └─┬ privateImplementation property (experimental)
│ │ ├── immutable
│ │ └── type: jsii-calc.IPrivatelyImplemented
+ │ ├─┬ class RootStructValidator (experimental)
+ │ │ └─┬ members
+ │ │ └─┬ static validate(struct) method (experimental)
+ │ │ ├── static
+ │ │ ├─┬ parameters
+ │ │ │ └─┬ struct
+ │ │ │ └── type: jsii-calc.RootStruct
+ │ │ └── returns: void
│ ├─┬ class RuntimeTypeChecking (experimental)
│ │ └─┬ members
│ │ ├── () initializer (experimental)
@@ -1886,6 +1894,12 @@ exports[`jsii-tree --all 1`] = `
│ │ ├── abstract
│ │ ├── immutable
│ │ └── type: Optional
+ │ ├─┬ interface NestedStruct (experimental)
+ │ │ └─┬ members
+ │ │ └─┬ numberProp property (experimental)
+ │ │ ├── abstract
+ │ │ ├── immutable
+ │ │ └── type: number
│ ├─┬ interface NullShouldBeTreatedAsUndefinedData (experimental)
│ │ └─┬ members
│ │ ├─┬ arrayWithThreeElementsAndUndefinedAsSecondArgument property (experimental)
@@ -1902,6 +1916,16 @@ exports[`jsii-tree --all 1`] = `
│ │ ├── abstract
│ │ ├── immutable
│ │ └── type: Optional
+ │ ├─┬ interface RootStruct (experimental)
+ │ │ └─┬ members
+ │ │ ├─┬ stringProp property (experimental)
+ │ │ │ ├── abstract
+ │ │ │ ├── immutable
+ │ │ │ └── type: string
+ │ │ └─┬ nestedStruct property (experimental)
+ │ │ ├── abstract
+ │ │ ├── immutable
+ │ │ └── type: Optional
│ ├─┬ interface SecondLevelStruct (experimental)
│ │ └─┬ members
│ │ ├─┬ deeperRequiredProp property (experimental)
@@ -2255,6 +2279,7 @@ exports[`jsii-tree --inheritance 1`] = `
│ ├── class PythonReservedWords
│ ├── class ReferenceEnumFromScopedPackage
│ ├── class ReturnsPrivateImplementationOfInterface
+ │ ├── class RootStructValidator
│ ├── class RuntimeTypeChecking
│ ├── class SingleInstanceTwoTypes
│ ├── class SingletonInt
@@ -2354,8 +2379,10 @@ exports[`jsii-tree --inheritance 1`] = `
│ ├── interface Hello
│ ├── interface Hello
│ ├── interface LoadBalancedFargateServiceProps
+ │ ├── interface NestedStruct
│ ├── interface NullShouldBeTreatedAsUndefinedData
│ ├── interface OptionalStruct
+ │ ├── interface RootStruct
│ ├── interface SecondLevelStruct
│ ├── interface StableStruct
│ ├── interface StructA
@@ -2914,6 +2941,9 @@ exports[`jsii-tree --members 1`] = `
│ │ └─┬ members
│ │ ├── () initializer
│ │ └── privateImplementation property
+ │ ├─┬ class RootStructValidator
+ │ │ └─┬ members
+ │ │ └── static validate(struct) method
│ ├─┬ class RuntimeTypeChecking
│ │ └─┬ members
│ │ ├── () initializer
@@ -3219,6 +3249,9 @@ exports[`jsii-tree --members 1`] = `
│ │ ├── memoryMiB property
│ │ ├── publicLoadBalancer property
│ │ └── publicTasks property
+ │ ├─┬ interface NestedStruct
+ │ │ └─┬ members
+ │ │ └── numberProp property
│ ├─┬ interface NullShouldBeTreatedAsUndefinedData
│ │ └─┬ members
│ │ ├── arrayWithThreeElementsAndUndefinedAsSecondArgument property
@@ -3226,6 +3259,10 @@ exports[`jsii-tree --members 1`] = `
│ ├─┬ interface OptionalStruct
│ │ └─┬ members
│ │ └── field property
+ │ ├─┬ interface RootStruct
+ │ │ └─┬ members
+ │ │ ├── stringProp property
+ │ │ └── nestedStruct property
│ ├─┬ interface SecondLevelStruct
│ │ └─┬ members
│ │ ├── deeperRequiredProp property
@@ -3439,6 +3476,7 @@ exports[`jsii-tree --types 1`] = `
│ ├── class PythonReservedWords
│ ├── class ReferenceEnumFromScopedPackage
│ ├── class ReturnsPrivateImplementationOfInterface
+ │ ├── class RootStructValidator
│ ├── class RuntimeTypeChecking
│ ├── class SingleInstanceTwoTypes
│ ├── class SingletonInt
@@ -3510,8 +3548,10 @@ exports[`jsii-tree --types 1`] = `
│ ├── interface Hello
│ ├── interface Hello
│ ├── interface LoadBalancedFargateServiceProps
+ │ ├── interface NestedStruct
│ ├── interface NullShouldBeTreatedAsUndefinedData
│ ├── interface OptionalStruct
+ │ ├── interface RootStruct
│ ├── interface SecondLevelStruct
│ ├── interface StableStruct
│ ├── interface StructA
diff --git a/packages/jsii-reflect/test/__snapshots__/type-system.test.js.snap b/packages/jsii-reflect/test/__snapshots__/type-system.test.js.snap
index 4609005af1..b46dddb198 100644
--- a/packages/jsii-reflect/test/__snapshots__/type-system.test.js.snap
+++ b/packages/jsii-reflect/test/__snapshots__/type-system.test.js.snap
@@ -90,6 +90,7 @@ Array [
"PythonReservedWords",
"ReferenceEnumFromScopedPackage",
"ReturnsPrivateImplementationOfInterface",
+ "RootStructValidator",
"RuntimeTypeChecking",
"SingleInstanceTwoTypes",
"SingletonInt",