Repository: Azure/azure-sdk-for-go
Pull request #23381 (2024-08-28 17:24:33)

[azcore] Add text [un]marshalling support to ResourceID
<!--
Thank you for contributing to the Azure SDK for Go.

Please verify the following before submitting your PR, thank you!
-->

It would be handy for [ResourceID](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource#ResourceID) to support the [encoding.TextMarshaler](https://pkg.go.dev/encoding@go1.23.0#TextMarshaler) and [encoding.TextUnmarshaler](https://pkg.go.dev/encoding@go1.23.0#TextUnmarshaler) interfaces so that, for example, JSON data that includes a resource ID string can be unmarshaled directly to a [ResourceID](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource#ResourceID) struct (and vice versa for marshaling).

- [x] The purpose of this PR is explained in this or a referenced issue.
- [x] The PR does not update generated files.
   - These files are managed by the codegen framework at [Azure/autorest.go][].
- [x] Tests are included and/or updated for code changes.
- [x] Updates to module CHANGELOG.md are included.
- [x] MIT license headers are included in each file.

[Azure/autorest.go]: https://github.com/Azure/autorest.go


github-actions[bot]: Thank you for your contribution @mbarnes! We will review the pull request and get back to you soon.
github-actions[bot]: Hi @mbarnes.  Thank you for your interest in helping to improve the Azure SDK experience and for your contribution.  We've noticed that there hasn't been recent engagement on this pull request.  If this is still an active work stream, please let us know by pushing some changes or leaving a comment.  Otherwise, we'll close this out in 7 days.
mbarnes: My suggestion is still valid.  Please leave open.
jhendrixMSFT: Mind rebasing on `main`?

Patch:
diff --git a/sdk/azcore/CHANGELOG.md b/sdk/azcore/CHANGELOG.md
index 7b9973b12e..f7713e06ce 100644
--- a/sdk/azcore/CHANGELOG.md
+++ b/sdk/azcore/CHANGELOG.md
@@ -5,6 +5,7 @@
 ### Features Added
 
 * Added field `OperationLocationResultPath` to `runtime.NewPollerOptions[T]` for LROs that use the `Operation-Location` pattern.
+* Support `encoding.TextMarshaler` and `encoding.TextUnmarshaler` interfaces in `arm.ResourceID`.
 
 ### Breaking Changes
 
diff --git a/sdk/azcore/arm/internal/resource/resource_identifier.go b/sdk/azcore/arm/internal/resource/resource_identifier.go
index 00f2d5a0ab..d9a4e36dcc 100644
--- a/sdk/azcore/arm/internal/resource/resource_identifier.go
+++ b/sdk/azcore/arm/internal/resource/resource_identifier.go
@@ -110,6 +110,21 @@ func (id *ResourceID) String() string {
 	return id.stringValue
 }
 
+// MarshalText returns a textual representation of the ResourceID
+func (id *ResourceID) MarshalText() ([]byte, error) {
+	return []byte(id.String()), nil
+}
+
+// UnmarshalText decodes the textual representation of a ResourceID
+func (id *ResourceID) UnmarshalText(text []byte) error {
+	newId, err := ParseResourceID(string(text))
+	if err != nil {
+		return err
+	}
+	*id = *newId
+	return nil
+}
+
 func newResourceID(parent *ResourceID, resourceTypeName string, resourceName string) *ResourceID {
 	id := &ResourceID{}
 	id.init(parent, chooseResourceType(resourceTypeName, parent), resourceName, true)


Test patch:
diff --git a/sdk/azcore/arm/internal/resource/resource_identifier_test.go b/sdk/azcore/arm/internal/resource/resource_identifier_test.go
index aab7c66f3a..162bf533d7 100644
--- a/sdk/azcore/arm/internal/resource/resource_identifier_test.go
+++ b/sdk/azcore/arm/internal/resource/resource_identifier_test.go
@@ -6,7 +6,10 @@
 
 package resource
 
-import "testing"
+import (
+	"encoding"
+	"testing"
+)
 
 func TestParseResourceIdentifier(t *testing.T) {
 	testData := map[string]*ResourceID{
@@ -220,6 +223,26 @@ func TestParseResourceIdentifier(t *testing.T) {
 	}
 }
 
+// Ensure ResourceID implements these interfaces
+var _ encoding.TextMarshaler = (*ResourceID)(nil)
+var _ encoding.TextUnmarshaler = (*ResourceID)(nil)
+
+func TestMarshalResourceIdentifier(t *testing.T) {
+	resourceID := &ResourceID{}
+	input := []byte("/subscriptions/17fecd63-33d8-4e43-ac6f-0aafa111b38d/resourceGroups/myRg/providers/Microsoft.ApiManagement/service/myServiceName/subscriptions/mySubs")
+	err := resourceID.UnmarshalText(input)
+	if err != nil {
+		t.Fatalf("unexpected error: %+v", err)
+	}
+	output, err := resourceID.MarshalText()
+	if err != nil {
+		t.Fatalf("unexpected error: %+v", err)
+	}
+	if string(output) != string(input) {
+		t.Fatalf("resource id changed, got %v, expected %v", string(output), string(input))
+	}
+}
+
 func equals(left, right *ResourceID) bool {
 	if left != nil && right != nil {
 		if left.String() != right.String() {