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

Loss of data when marshaling model types #12227

Closed
viking66 opened this issue Aug 13, 2020 · 11 comments
Closed

Loss of data when marshaling model types #12227

viking66 opened this issue Aug 13, 2020 · 11 comments
Labels
customer-reported Issues that are reported by GitHub users external to the Azure organization. Mgmt This issue is related to a management-plane library. needs-author-feedback Workflow: More information is needed from author to address the issue. no-recent-activity There has been no recent activity on this issue. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that

Comments

@viking66
Copy link

Bug Report

  • import path: github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-05-01/network

  • SDK version: v45.0.0

  • go version: go version go1.14.6 darwin/amd64

  • What happened?
    I'm working on a project that uses golang to call services within azure to collect data and then marshal that data and pass it to another service in the system which unmarshals that data and processes it. The data I get back from the azure service call contains all the fields I expect but I'm losing data when I marshal it to json.

  • What did you expect or want to happen?
    I expect the marshaled data to include all the fields that were present in the service response.

  • How can we reproduce it?
    Use golang to call network.ListAllComplete then marshal the data via json.Marshal and inspect the resulting json data. Lots of the fields from nested types are now missing.

  • Anything we should know about your environment.
    There's nothing special about my environment.

  • Root cause (from my perspective)
    Golang allows you to provide custom marshalers for your types by implementing a MarshalJSON() ([]byte, error) method on the type. Scanning through the code in https://github.com/Azure/azure-sdk-for-go/blob/master/services/network/mgmt/2020-05-01/network/models.go I see there's lots of custom marshalers that only include a subset of the fields from the type they're marshaling.

  • Proposed solution
    All the types appear to include json:"foo..." tags which allows golang to automatically handle the json marshaling without having to define custom marshalers and unmarshalers. So as far as I can tell, you should be able to remove the custom (un)marshalers and the problem would be fixed.

  • Alternative solution
    Update the custom (un)marshalers to include all the expected fields.

@ghost ghost added needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. customer-reported Issues that are reported by GitHub users external to the Azure organization. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels Aug 13, 2020
@ArcturusZhang
Copy link
Member

ArcturusZhang commented Aug 14, 2020

Hi @viking66 thanks for this issue.

Sorry for the inconvenience but this is by our go SDK design.

In the definition of our REST API specs for Azure, there are a lot of read-only properties, which are not allowed to be in the request body. The custom marshaller functions are designed to serve the marshalling of the models into a request body, therefore it omits any property that is marked as read-only.

If you want to marshal everything to JSON, just create an alias type, like this:

func main() {
	type test compute.VirtualMachine
	vm := test{
		Name: to.StringPtr("test"),
		Location: to.StringPtr("eastus"),
	}
	b, err := json.Marshal(vm)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}

You will get the result of

{"name":"test","location":"eastus","tags":null}

As a reference, you could check the custom marshaler definition here, which will ignore name.

This will by-pass golang's marshaller mechanism and gives you every property using the default marshaller.

Hope this helps, thanks

@ArcturusZhang ArcturusZhang added customer-response-expected and removed needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. labels Aug 14, 2020
@viking66
Copy link
Author

The alias trick works as long as the fields of the struct you alias don't also have custom marshalers. For example, if I try to marshal network.VirtualNetwork using an alias in v45.0.0 of the sdk I still lose data but if I use v44.0.0 I'm not losing the data I care about.

The difference between v44.0.0 and v45.0.0 is how network.VirtualNetwork's network.VirtualNetworkPropertiesFormat embedded type is marshaled. In v44.0.0 network.VirtualNetworkPropertiesFormat does not implement MarshalJSON but in v45.0.0 it does. As a result, in v45.0.0 a field like network.VirtualNetwork.Name gets dropped even when using an alias for VirtualNetwork because of the way go promotes the MarshalJSON method.

@ArcturusZhang
Copy link
Member

@viking66 you are totally correct. I overlooked this could be recursive.

And the reason why we have to make this change is that some services do not accept a request body with read-only field assigned - to be specific this time it is the loadbalancer is causing trouble. Please refer to this issue and this issue for more information

@jhendrixMSFT do you have any good solution for this problem?

@jhendrixMSFT
Copy link
Member

Our solution for track 2 is to add a tag to any read-only fields.

https://github.com/Azure/autorest.go/blob/track2/test/autorest/generated/complexgroup/models.go#L695

When creating the request, we recursively look for the tag, and if present, we clone the request object graph omitting all read-only fields.

https://github.com/Azure/azure-sdk-for-go/blob/master/sdk/azcore/request.go#L221

You could consider back-porting this to track 1. My only concern here is if any consumers have come to rely on the current behavior.

@ArcturusZhang
Copy link
Member

Yeah, back-porting it to track 1 would be an elegant solution. For those are depending on the current behaviour, maybe they could also switch to the approach that are using the cloneWithoutReadOnlyFields method.

I will take a look if it is possible

@jhendrixMSFT
Copy link
Member

By dependent on the old behavior, I meant that some customers might prefer that calls to json.Marshal exclude the R/O data. While I think this is unlikely, I'm just speculating based on the complaints we've had with the current behavior. We might need to provide a way to opt-in to this old behavior (I would prefer not to if possible).

@viking66
Copy link
Author

Is there any ETA for a solution to this problem?

@AdallomRoy
Copy link

AdallomRoy commented Sep 24, 2020

We are also experiencing this. Any ETA?
@viking66 as a workaround, you can first serialize the object using structs Map (https://github.com/fatih/structs) and then to json.

@tzhanl tzhanl added the Mgmt This issue is related to a management-plane library. label Nov 23, 2020
@ghost ghost added the needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team label Sep 10, 2021
@lirenhe
Copy link
Member

lirenhe commented Sep 15, 2021

Our library for the new version will GA this year and we already have the preview https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/network/armnetwork. Please have a try on whether it could solve your problem. We won't fix it in old version of the SDK.

@RickWinter RickWinter added needs-author-feedback Workflow: More information is needed from author to address the issue. and removed needs-team-attention Workflow: This issue needs attention from Azure service team or SDK team customer-response-expected labels Sep 17, 2021
@ghost ghost added the no-recent-activity There has been no recent activity on this issue. label Sep 24, 2021
@ghost
Copy link

ghost commented Sep 24, 2021

Hi, we're sending this friendly reminder because we haven't heard back from you in a while. We need more information about this issue to help address it. Please be sure to give us your input within the next 7 days. If we don't hear back from you within 14 days of this comment the issue will be automatically closed. Thank you!

@ghost ghost removed the no-recent-activity There has been no recent activity on this issue. label Sep 27, 2021
@ghost ghost added the no-recent-activity There has been no recent activity on this issue. label Oct 4, 2021
@ghost
Copy link

ghost commented Oct 4, 2021

Hi, we're sending this friendly reminder because we haven't heard back from you in a while. We need more information about this issue to help address it. Please be sure to give us your input within the next 7 days. If we don't hear back from you within 14 days of this comment the issue will be automatically closed. Thank you!

@ghost ghost closed this as completed Nov 3, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Apr 11, 2023
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
customer-reported Issues that are reported by GitHub users external to the Azure organization. Mgmt This issue is related to a management-plane library. needs-author-feedback Workflow: More information is needed from author to address the issue. no-recent-activity There has been no recent activity on this issue. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that
Projects
None yet
Development

No branches or pull requests

7 participants