-
Notifications
You must be signed in to change notification settings - Fork 294
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
Generic golang interface{} serialization gives an empty object for structs #1326
Comments
Reviewed this case from a jsii perspective, and here are my findings (re-stating the obvious, too):
There is no straight-forward way to explicitly represent "object with a specified JSON representation" in the jsii type model today except for using I tend to think it would be better to model properties typed as "opaque" object in the underlying schema to the map type, so that users don't get caught in this particular trap. Alternatively, we may want to consider requesting new jsii features, such as ability to explicitly bind a Now - while this is not very elegant, you can work around this issue today by actually pointer here instead of xp.NewCompositeResourceDefinition(chart, jsii.String("CrossPlane"), &xp.CompositeResourceDefinitionProps{
Spec: &xp.CompositeResourceDefinitionSpec{
Group: jsii.String("group"),
Names: &xp.CompositeResourceDefinitionSpecNames{
Kind: jsii.String("kind"),
Plural: jsii.String("kinds"),
},
Versions: &([]*xp.CompositeResourceDefinitionSpecVersions{
{
Name: jsii.String("v1alpha1"),
Referenceable: jsii.Bool(true),
Served: jsii.Bool(true),
Schema: &xp.CompositeResourceDefinitionSpecVersionsSchema{
OpenApiv3Schema: &map[string]interface{}{
"type": "object",
},
},
},
}),
},
}) results in the following output: apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: test-chart-crossplane-c893e157
spec:
group: group
names:
kind: kind
plural: kinds
versions:
- name: v1alpha1
referenceable: true
schema:
openAPIV3Schema:
type: object
served: true |
I'm still going to verify if it'd be feasible to detect "exported" (aka public) properties of these structs and appropriately register them upon proxy object creation. This might be enough to make such scenarios work. |
I was able to confirm that registering properties correctly here results in the expected behavior. I'll make a PR into the jsii runtime for Go with this soon (I need to write a couple of tests first). |
When passing arbitrary structs through an `interface{}` type, the JS value had no properties or methods, leading to it having an empty object JSON representation. In order to improve the situation, discover exported properties of such structs, and register them as property callbacks, more closely matching the behavior of JS in the same configuration. The callbacks use the same naming transformation as the standard JSON serialization mechanism in go: using the `json` tag if present with the same semantics as `encoding/json`, and fall back to the raw field name otherwise (with no case conversion applied). Related: cdk8s-team/cdk8s#1326
Submitted aws/jsii#4104, which I believe addresses the issue at hand here (I mean - it does in the tests I ran with your original code snippet above). |
@RomainMuller thanks for diving into this! |
When passing arbitrary structs through an `interface{}` type, the JS value had no properties or methods, leading to it having an empty object JSON representation. In order to improve the situation, discover exported properties of such structs, and register them as property callbacks, more closely matching the behavior of JS in the same configuration. The callbacks use the same naming transformation as the standard JSON serialization mechanism in go: using the `json` tag if present with the same semantics as `encoding/json`, and fall back to the raw field name otherwise (with no case conversion applied). Related: cdk8s-team/cdk8s#1326 --- By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license]. [Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
@RomainMuller I don't really get what had been patched
Worked previously anyway, but
Gives me Also And instead type PipelineProps struct {
Metadata *cdk8s.ApiObjectMetadata `field:"optional" json:"metadata" yaml:"metadata"`
} I'd like to get type PipelineProps struct {
Metadata *cdk8s.ApiObjectMetadata `field:"optional" json:"metadata" yaml:"metadata"`
PipelineSpec *PipelineSpec `field:"optional" json:"metadata" yaml:"spec"`
}
type PipelineSpec struct {
Schema *PipelineSchema `field:"optional" json:"schema" yaml:"schema"`
}
type PipelineSchema struct {
OpenApiv3Schema interface{} `field:"optional" json:"openApiv3Schema" yaml:"openApiv3Schema"`
} or similar... It skips So, I'm stuck with manual patching with CDK8S escape hatches. I'm using latest "devDependencies": {
"cdk8s": "~2.7.77",
"cdk8s-cli": "~2.2.51",
"constructs": "~10.2.35",
"jsii": "~5.1.0",
"@jsii/runtime": "~1.82.0"
} with |
func ToMap[T any](obj T) map[string]interface{} {
result := make(map[string]interface{})
marshalled, _ := json.Marshal(obj)
err := json.Unmarshal(marshalled, &result)
if err != nil {
log.Error().Err(err).Msg("can't convert to map[string]interface{}")
}
return result
} does the trick, most of the time... |
This issue has not received any attention in 1 year and will be closed soon. If you want to keep it open, please leave a comment below @mentioning a maintainer. |
Description of the bug:
I'm facing something similar to #1291 with Crossplane.
Crossplane CompositeResourceDefinition (XRD) CRD defines openAPIV3Schema as a
type: object
, which results in an empty object synthesis and plaininterface{}
generation.So, for a crossplane XRD, this
CRD codegen gives an
interface{}
for atype: object
schemait synthesizes just an empty object
{}
, disregarding the contentsIt should be possible to cast existing
struct
tointerface{}
, or at least convert it tomapstructure
asmap[string]interface{}
using the respective yaml reflection tags out of the existing k8s JsonSchemaProps, to overcome this. But I'd like a bit more concise solution, or at least an exception During Synthesis, instead of an empty output.Reproduction Steps:
type: object
which would generateinterface{}
struct{}
with something thereEnvironment:
This is 🐛 Bug Report
The text was updated successfully, but these errors were encountered: