Skip to content

Commit baf6ce2

Browse files
Fix handling of multiple formats of contextual metadata
1 parent 42222b7 commit baf6ce2

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

api/admin/asset.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package admin
66

77
import (
88
"context"
9+
"encoding/json"
910
"time"
1011

1112
"github.com/cloudinary/cloudinary-go/v2/api"
@@ -148,6 +149,38 @@ type AssetContextResult struct {
148149
Custom map[string]string `json:"custom"`
149150
}
150151

152+
func (m *AssetContextResult) UnmarshalJSON(data []byte) error {
153+
// map format
154+
var mapData struct {
155+
Custom map[string]string `json:"custom"`
156+
}
157+
if err := json.Unmarshal(data, &mapData); err == nil {
158+
*m = AssetContextResult{
159+
Custom: mapData.Custom,
160+
}
161+
return nil
162+
}
163+
164+
// array format
165+
var arrayData []struct {
166+
Key string `json:"key"`
167+
Value string `json:"value"`
168+
}
169+
if err := json.Unmarshal(data, &arrayData); err != nil {
170+
return err
171+
}
172+
173+
result := AssetContextResult{
174+
Custom: make(map[string]string),
175+
}
176+
for _, item := range arrayData {
177+
result.Custom[item.Key] = item.Value
178+
}
179+
*m = result
180+
181+
return nil
182+
}
183+
151184
// UpdateAssetParams are the parameters for UpdateAsset.
152185
type UpdateAssetParams struct {
153186
AssetType api.AssetType `json:"-"`

api/admin/asset_acceptance_test.go

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import (
66
"context"
77
"encoding/json"
88
"fmt"
9-
"github.com/cloudinary/cloudinary-go/v2/api"
10-
"github.com/cloudinary/cloudinary-go/v2/api/admin"
11-
"github.com/cloudinary/cloudinary-go/v2/internal/cldtest"
129
"net/url"
1310
"reflect"
1411
"testing"
12+
13+
"github.com/cloudinary/cloudinary-go/v2/api"
14+
"github.com/cloudinary/cloudinary-go/v2/api/admin"
15+
"github.com/cloudinary/cloudinary-go/v2/internal/cldtest"
1516
)
1617

1718
// Acceptance test cases for `asset` method
@@ -95,6 +96,86 @@ func getAssetTestCases() []AdminAPIAcceptanceTestCase {
9596
},
9697
)
9798

99+
// Test case for AssetContextResult with map format
100+
assetWithMapContext := admin.AssetResult{
101+
AssetID: "1",
102+
PublicID: cldtest.PublicID,
103+
Context: admin.AssetContextResult{
104+
Custom: map[string]string{
105+
"key1": "value1",
106+
"key2": "value2",
107+
},
108+
},
109+
}
110+
responseJsonMapContext, _ := json.Marshal(assetWithMapContext)
111+
112+
testCases = append(testCases, AdminAPIAcceptanceTestCase{
113+
Name: "Asset response with context in map format",
114+
RequestTest: func(api *admin.API, ctx context.Context) (interface{}, error) {
115+
return api.Asset(ctx, admin.AssetParams{PublicID: cldtest.PublicID})
116+
},
117+
ResponseTest: func(response interface{}, t *testing.T) {
118+
v, ok := response.(*admin.AssetResult)
119+
if !ok {
120+
t.Errorf("Response should be type of AssetResult, %s given", reflect.TypeOf(response))
121+
}
122+
v.Response = nil // omit raw response comparison
123+
if !reflect.DeepEqual(*v, assetWithMapContext) {
124+
t.Errorf("Response asset should be %v, %v given", assetWithMapContext, *v)
125+
}
126+
},
127+
ExpectedRequest: cldtest.ExpectedRequestParams{
128+
Method: "GET",
129+
URI: "/resources/image/upload/" + cldtest.PublicID,
130+
},
131+
JsonResponse: string(responseJsonMapContext),
132+
ExpectedCallCount: 1,
133+
})
134+
135+
// Test case for AssetContextResult with array format
136+
// The JSON response will have context as an array, but the parsed result should be the same
137+
assetWithArrayContext := admin.AssetResult{
138+
AssetID: "1",
139+
PublicID: cldtest.PublicID,
140+
Context: admin.AssetContextResult{
141+
Custom: map[string]string{
142+
"key1": "value1",
143+
"key2": "value2",
144+
},
145+
},
146+
}
147+
responseJsonArrayContext, _ := json.Marshal(map[string]interface{}{
148+
"asset_id": "1",
149+
"public_id": cldtest.PublicID,
150+
"context": []map[string]string{
151+
{"key": "key1", "value": "value1"},
152+
{"key": "key2", "value": "value2"},
153+
},
154+
})
155+
156+
testCases = append(testCases, AdminAPIAcceptanceTestCase{
157+
Name: "Asset response with context in array format",
158+
RequestTest: func(api *admin.API, ctx context.Context) (interface{}, error) {
159+
return api.Asset(ctx, admin.AssetParams{PublicID: cldtest.PublicID})
160+
},
161+
ResponseTest: func(response interface{}, t *testing.T) {
162+
v, ok := response.(*admin.AssetResult)
163+
if !ok {
164+
t.Errorf("Response should be type of AssetResult, %s given", reflect.TypeOf(response))
165+
}
166+
v.Response = nil // omit raw response comparison
167+
if !reflect.DeepEqual(*v, assetWithArrayContext) {
168+
t.Errorf("Response asset should be %v, %v given", assetWithArrayContext, *v)
169+
}
170+
},
171+
ExpectedRequest: cldtest.ExpectedRequestParams{
172+
Method: "GET",
173+
URI: "/resources/image/upload/" + cldtest.PublicID,
174+
},
175+
JsonResponse: string(responseJsonArrayContext),
176+
ExpectedCallCount: 1,
177+
})
178+
98179
return testCases
99180
}
100181

0 commit comments

Comments
 (0)